Subversion Repositories Kolibri OS

Rev

Rev 6876 | Go to most recent revision | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 6876 Rev 9953
1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2
;;                                                              ;;
2
;;                                                              ;;
3
;; Copyright (C) KolibriOS team 2004-2016. All rights reserved. ;;
3
;; Copyright (C) KolibriOS team 2004-2016. All rights reserved. ;;
4
;;  Distributed under terms of the GNU General Public License.  ;;
4
;;  Distributed under terms of the GNU General Public License.  ;;
5
;;                                                              ;;
5
;;                                                              ;;
6
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
6
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
7
 
7
 
8
$Revision: 6876 $
8
$Revision: 9953 $
9
 
9
 
10
; NTFS external functions
10
; NTFS external functions
11
;   in:
11
;   in:
12
; ebx -> parameter structure of sysfunc 70
12
; ebx -> parameter structure of sysfunc 70
13
; ebp -> NTFS structure
13
; ebp -> NTFS structure
14
; esi -> path string in UTF-8
14
; esi -> path string in UTF-8
15
;   out:
15
;   out:
16
; eax, ebx = return values for sysfunc 70
16
; eax, ebx = return values for sysfunc 70
17
iglobal
17
iglobal
18
align 4
18
align 4
19
ntfs_user_functions:
19
ntfs_user_functions:
20
        dd      ntfs_free
20
        dd      ntfs_free
21
        dd      (ntfs_user_functions_end - ntfs_user_functions - 4) / 4
21
        dd      (ntfs_user_functions_end - ntfs_user_functions - 4) / 4
22
        dd      ntfs_ReadFile
22
        dd      ntfs_ReadFile
23
        dd      ntfs_ReadFolder
23
        dd      ntfs_ReadFolder
24
        dd      ntfs_CreateFile
24
        dd      ntfs_CreateFile
25
        dd      ntfs_WriteFile
25
        dd      ntfs_WriteFile
26
        dd      ntfs_SetFileEnd
26
        dd      ntfs_SetFileEnd
27
        dd      ntfs_GetFileInfo
27
        dd      ntfs_GetFileInfo
28
        dd      ntfs_SetFileInfo
28
        dd      ntfs_SetFileInfo
29
        dd      0
29
        dd      0
30
        dd      ntfs_Delete
30
        dd      ntfs_Delete
31
        dd      ntfs_CreateFolder
31
        dd      ntfs_CreateFolder
32
ntfs_user_functions_end:
32
ntfs_user_functions_end:
33
endg
33
endg
34
 
34
 
35
; Basic concepts:
35
; Basic concepts:
36
; File is a FileRecord in the $MFT.
36
; File is a FileRecord in the $MFT.
37
; $MFT is a file, that consists of FileRecords and starts with FileRecord of itself.
37
; $MFT is a file, that consists of FileRecords and starts with FileRecord of itself.
38
; FileRecord (FILE) consists of a header and attributes.
38
; FileRecord (FILE) consists of a header and attributes.
39
; Attribute consists of a header and a body.
39
; Attribute consists of a header and a body.
40
; Attribute's body can be inside (resident) or outside of FileRecord.
40
; Attribute's body can be inside (resident) or outside of FileRecord.
41
; File's data is a body of $Data (80h) attribute.
41
; File's data is a body of $Data (80h) attribute.
42
; FileRecords is a data of the $MFT file.
42
; FileRecords is a data of the $MFT file.
43
; Directory is a file, that consists of index nodes.
43
; Directory is a file, that consists of index nodes.
44
; Resident index node is always located in a body of $IndexRoot (90h) attribute.
44
; Resident index node is always located in a body of $IndexRoot (90h) attribute.
45
; Body of $IndexAllocation (A0h) attribute is always non resident
45
; Body of $IndexAllocation (A0h) attribute is always non resident
46
;  and consists of IndexRecords.
46
;  and consists of IndexRecords.
47
; IndexRecord (INDX) consists of a header and an index node.
47
; IndexRecord (INDX) consists of a header and an index node.
48
; Index node consists of a header and indexes.
48
; Index node consists of a header and indexes.
49
; Index consists of a header and a copy of indexed attribute's body.
49
; Index consists of a header and a copy of indexed attribute's body.
50
; Directories index $Filename (30h) attribute of all existing files.
50
; Directories index $Filename (30h) attribute of all existing files.
51
; $IndexRoot and $IndexAllocation attributes of a directory has a name — $I30.
51
; $IndexRoot and $IndexAllocation attributes of a directory has a name — $I30.
52
 
52
 
53
; Offsets:
53
; Offsets:
54
    ; record header
54
    ; record header
55
magic = 0
55
magic = 0
56
updateSequenceOffset = 4
56
updateSequenceOffset = 4
57
updateSequenceSize = 6
57
updateSequenceSize = 6
58
    ; FileRecord header
58
    ; FileRecord header
59
reuseCounter = 16
59
reuseCounter = 16
60
hardLinkCounter = 12h
60
hardLinkCounter = 12h
61
attributeOffset = 14h
61
attributeOffset = 14h
62
recordFlags = 16h
62
recordFlags = 16h
63
recordRealSize = 18h
63
recordRealSize = 18h
64
recordAllocatedSize = 1ch
64
recordAllocatedSize = 1ch
65
baseRecordReference = 20h       ; for auxiliary records
65
baseRecordReference = 20h       ; for auxiliary records
66
baseRecordReuse = 26h
66
baseRecordReuse = 26h
67
newAttributeID = 28h
67
newAttributeID = 28h
68
    ; attribute header
68
    ; attribute header
69
attributeType = 0
69
attributeType = 0
70
sizeWithHeader = 4
70
sizeWithHeader = 4
71
nonResidentFlag = 8
71
nonResidentFlag = 8
72
nameLength = 9
72
nameLength = 9
73
nameOffset = 10
73
nameOffset = 10
74
attributeFlags = 12
74
attributeFlags = 12
75
attributeID = 14
75
attributeID = 14
76
    ; resident attribute header
76
    ; resident attribute header
77
sizeWithoutHeader = 10h
77
sizeWithoutHeader = 10h
78
attributeOffset = 14h
78
attributeOffset = 14h
79
indexedFlag = 16h
79
indexedFlag = 16h
80
    ; non resident attribute header
80
    ; non resident attribute header
81
firstVCN = 10h
81
firstVCN = 10h
82
lastVCN = 18h
82
lastVCN = 18h
83
dataRunsOffset = 20h
83
dataRunsOffset = 20h
84
attributeAllocatedSize = 28h
84
attributeAllocatedSize = 28h
85
attributeRealSize = 30h
85
attributeRealSize = 30h
86
initialDataSize = 38h
86
initialDataSize = 38h
87
    ; $IndexRoot
87
    ; $IndexRoot
88
indexedAttributesType = 0
88
indexedAttributesType = 0
89
collationRule = 4
89
collationRule = 4
90
indexRecordSize = 8
90
indexRecordSize = 8
91
indexRecordSizeClus = 12        ; in sectors if less than one cluster
91
indexRecordSizeClus = 12        ; in sectors if less than one cluster
92
rootNode = 16
92
rootNode = 16
93
    ; IndexRecord header
93
    ; IndexRecord header
94
recordVCN = 16
94
recordVCN = 16
95
recordNode = 18h
95
recordNode = 18h
96
    ; node header
96
    ; node header
97
indexOffset = 0
97
indexOffset = 0
98
nodeRealSize = 4
98
nodeRealSize = 4
99
nodeAllocatedSize = 8
99
nodeAllocatedSize = 8
100
nonLeafFlag = 12
100
nonLeafFlag = 12
101
    ; $Filename index
101
    ; $Filename index
102
fileRecordReference = 0
102
fileRecordReference = 0
103
fileReferenceReuse = 6
103
fileReferenceReuse = 6
104
indexAllocatedSize = 8
104
indexAllocatedSize = 8
105
indexRawSize = 10
105
indexRawSize = 10
106
indexFlags = 12
106
indexFlags = 12
107
directoryRecordReference = 16
107
directoryRecordReference = 16
108
directoryReferenceReuse = 16h
108
directoryReferenceReuse = 16h
109
fileCreated = 18h
109
fileCreated = 18h
110
fileModified = 20h
110
fileModified = 20h
111
recordModified = 28h
111
recordModified = 28h
112
fileAccessed = 30h
112
fileAccessed = 30h
113
fileAllocatedSize = 38h
113
fileAllocatedSize = 38h
114
fileRealSize = 40h
114
fileRealSize = 40h
115
fileFlags = 48h
115
fileFlags = 48h
116
fileNameLength = 50h
116
fileNameLength = 50h
117
namespace = 51h
117
namespace = 51h
118
fileName = 52h
118
fileName = 52h
119
 
119
 
120
struct NTFS PARTITION
120
struct NTFS PARTITION
121
Lock                MUTEX   ; Currently operations with one partition
121
Lock                MUTEX   ; Currently operations with one partition
122
; can not be executed in parallel since the legacy code is not ready.
122
; can not be executed in parallel since the legacy code is not ready.
123
sectors_per_cluster dd  ?
123
sectors_per_cluster dd  ?
124
mft_cluster         dd  ?   ; location
124
mft_cluster         dd  ?   ; location
125
mftmirr_cluster     dd  ?   ; location
125
mftmirr_cluster     dd  ?   ; location
126
frs_size            dd  ?   ; in bytes
126
frs_size            dd  ?   ; in bytes
127
frs_buffer          dd  ?   ; MFT fileRecord buffer
127
frs_buffer          dd  ?   ; MFT fileRecord buffer
128
mft_retrieval_end   dd  ?
128
mft_retrieval_end   dd  ?
129
mftSize             dd  ?   ; in sectors
129
mftSize             dd  ?   ; in sectors
130
cur_index_size      dd  ?   ; in sectors
130
cur_index_size      dd  ?   ; in sectors
131
cur_index_buf       dd  ?   ; index node buffer
131
cur_index_buf       dd  ?   ; index node buffer
132
secondIndexBuffer   dd  ?
132
secondIndexBuffer   dd  ?
133
BitmapBuffer        dd  ?
133
BitmapBuffer        dd  ?
134
BitmapTotalSize     dd  ?   ; bytes reserved
134
BitmapTotalSize     dd  ?   ; bytes reserved
135
BitmapSize          dd  ?   ; bytes readen
135
BitmapSize          dd  ?   ; bytes readen
136
BitmapLocation      dd  ?   ; starting sector
136
BitmapLocation      dd  ?   ; starting sector
137
BitmapStart         dd  ?   ; first byte after area, reserved for MFT
137
BitmapStart         dd  ?   ; first byte after area, reserved for MFT
138
mftBitmapBuffer     dd  ?   ; one cluster
138
mftBitmapBuffer     dd  ?   ; one cluster
139
mftBitmapSize       dd  ?   ; bytes readen
139
mftBitmapSize       dd  ?   ; bytes readen
140
mftBitmapLocation   dd  ?   ; starting sector
140
mftBitmapLocation   dd  ?   ; starting sector
141
 
141
 
142
attr_size           dq  ?
142
attr_size           dq  ?
143
attr_offs           dd  ?
143
attr_offs           dd  ?
144
attr_list           dd  ?
144
attr_list           dd  ?
145
attr_iBaseRecord    dd  ?
145
attr_iBaseRecord    dd  ?
146
cur_attr            dd  ?   ; attribute type
146
cur_attr            dd  ?   ; attribute type
147
cur_iRecord         dd  ?   ; number of fileRecord in MFT
147
cur_iRecord         dd  ?   ; number of fileRecord in MFT
148
cur_offs            dd  ?   ; attribute VCN in sectors
148
cur_offs            dd  ?   ; attribute VCN in sectors
149
cur_size            dd  ?   ; max sectors to read
149
cur_size            dd  ?   ; max sectors to read
150
cur_buf             dd  ?
150
cur_buf             dd  ?
151
cur_read            dd  ?   ; bytes readen
151
cur_read            dd  ?   ; bytes readen
152
cur_tail            dd  ?
152
cur_tail            dd  ?
153
cur_subnode_size    dd  ?
153
cur_subnode_size    dd  ?
154
LastRead            dd  ?   ; last readen block of sectors
154
LastRead            dd  ?   ; last readen block of sectors
155
mftLastRead         dd  ?
155
mftLastRead         dd  ?
156
rootLastRead        dd  ?
156
rootLastRead        dd  ?
157
nodeLastRead        dd  ?
157
nodeLastRead        dd  ?
158
indexRoot           dd  ?
158
indexRoot           dd  ?
159
indexPointer        dd  ?
159
indexPointer        dd  ?
160
newRecord           dd  ?
160
newRecord           dd  ?
161
fileDataStart       dd  ?   ; starting cluster
161
fileDataStart       dd  ?   ; starting cluster
162
fileDataSize        dd  ?   ; in clusters
162
fileDataSize        dd  ?   ; in clusters
163
fileDataBuffer      dd  ?
163
fileDataBuffer      dd  ?
164
fileRealSize        dd  ?   ; in bytes
164
fileRealSize        dd  ?   ; in bytes
165
fragmentCount       db  ?
165
fragmentCount       db  ?
166
bCanContinue        db  ?
166
bCanContinue        db  ?
167
bFolder             db  ?
167
bFolder             db  ?
168
bWriteAttr          db  ?   ; Warning: Don't forget to turn off!!!
168
bWriteAttr          db  ?   ; Warning: Don't forget to turn off!!!
169
 
169
 
170
mft_retrieval       rb  512
170
mft_retrieval       rb  512
171
align0  rb  1024-NTFS.align0
171
align0  rb  1024-NTFS.align0
172
attrlist_buf        rb  1024
172
attrlist_buf        rb  1024
173
attrlist_mft_buf    rb  1024
173
attrlist_mft_buf    rb  1024
174
bitmap_buf          rb  1024
174
bitmap_buf          rb  1024
175
ends
175
ends
176
 
176
 
177
ntfs_test_bootsec:
177
ntfs_test_bootsec:
178
; in: ebx -> buffer, edx = size of partition
178
; in: ebx -> buffer, edx = size of partition
179
; out: CF=1 -> invalid
179
; out: CF=1 -> invalid
180
; 1. Name=='NTFS    '
180
; 1. Name=='NTFS    '
181
        cmp     dword [ebx+3], 'NTFS'
181
        cmp     dword [ebx+3], 'NTFS'
182
        jnz     .no
182
        jnz     .no
183
        cmp     dword [ebx+7], '    '
183
        cmp     dword [ebx+7], '    '
184
        jnz     .no
184
        jnz     .no
185
; 2. Number of bytes per sector is the same as for physical device
185
; 2. Number of bytes per sector is the same as for physical device
186
; (that is, 0x200 for hard disk)
186
; (that is, 0x200 for hard disk)
187
        cmp     word [ebx+11], 0x200
187
        cmp     word [ebx+11], 0x200
188
        jnz     .no
188
        jnz     .no
189
; 3. Number of sectors per cluster must be power of 2
189
; 3. Number of sectors per cluster must be power of 2
190
        movzx   eax, byte [ebx+13]
190
        movzx   eax, byte [ebx+13]
191
        dec     eax
191
        dec     eax
192
        js      .no
192
        js      .no
193
        test    al, [ebx+13]
193
        test    al, [ebx+13]
194
        jnz     .no
194
        jnz     .no
195
; 4. FAT parameters must be zero
195
; 4. FAT parameters must be zero
196
        cmp     word [ebx+14], 0
196
        cmp     word [ebx+14], 0
197
        jnz     .no
197
        jnz     .no
198
        cmp     dword [ebx+16], 0
198
        cmp     dword [ebx+16], 0
199
        jnz     .no
199
        jnz     .no
200
        cmp     byte [ebx+20], 0
200
        cmp     byte [ebx+20], 0
201
        jnz     .no
201
        jnz     .no
202
        cmp     word [ebx+22], 0
202
        cmp     word [ebx+22], 0
203
        jnz     .no
203
        jnz     .no
204
        cmp     dword [ebx+32], 0
204
        cmp     dword [ebx+32], 0
205
        jnz     .no
205
        jnz     .no
206
; 5. Number of sectors <= partition size
206
; 5. Number of sectors <= partition size
207
        cmp     dword [ebx+0x2C], 0
207
        cmp     dword [ebx+0x2C], 0
208
        ja      .no
208
        ja      .no
209
        cmp     [ebx+0x28], edx
209
        cmp     [ebx+0x28], edx
210
        ja      .no
210
        ja      .no
211
; 6. $MFT and $MFTMirr clusters must be within partition
211
; 6. $MFT and $MFTMirr clusters must be within partition
212
        cmp     dword [ebx+0x34], 0
212
        cmp     dword [ebx+0x34], 0
213
        ja      .no
213
        ja      .no
214
        push    edx
214
        push    edx
215
        movzx   eax, byte [ebx+13]
215
        movzx   eax, byte [ebx+13]
216
        mul     dword [ebx+0x30]
216
        mul     dword [ebx+0x30]
217
        test    edx, edx
217
        test    edx, edx
218
        pop     edx
218
        pop     edx
219
        jnz     .no
219
        jnz     .no
220
        cmp     eax, edx
220
        cmp     eax, edx
221
        ja      .no
221
        ja      .no
222
        cmp     dword [ebx+0x3C], 0
222
        cmp     dword [ebx+0x3C], 0
223
        ja      .no
223
        ja      .no
224
        push    edx
224
        push    edx
225
        movzx   eax, byte [ebx+13]
225
        movzx   eax, byte [ebx+13]
226
        mul     dword [ebx+0x38]
226
        mul     dword [ebx+0x38]
227
        test    edx, edx
227
        test    edx, edx
228
        pop     edx
228
        pop     edx
229
        jnz     .no
229
        jnz     .no
230
        cmp     eax, edx
230
        cmp     eax, edx
231
        ja      .no
231
        ja      .no
232
; 7. Clusters per FRS must be either power of 2 or between -31 and -9
232
; 7. Clusters per FRS must be either power of 2 or between -31 and -9
233
        movsx   eax, byte [ebx+0x40]
233
        movsx   eax, byte [ebx+0x40]
234
        cmp     al, -31
234
        cmp     al, -31
235
        jl      .no
235
        jl      .no
236
        cmp     al, -9
236
        cmp     al, -9
237
        jle     @f
237
        jle     @f
238
        dec     eax
238
        dec     eax
239
        js      .no
239
        js      .no
240
        test    [ebx+0x40], al
240
        test    [ebx+0x40], al
241
        jnz     .no
241
        jnz     .no
242
@@:         ; 8. Same for clusters per IndexAllocationBuffer
242
@@:         ; 8. Same for clusters per IndexAllocationBuffer
243
        movsx   eax, byte [ebx+0x44]
243
        movsx   eax, byte [ebx+0x44]
244
        cmp     al, -31
244
        cmp     al, -31
245
        jl      .no
245
        jl      .no
246
        cmp     al, -9
246
        cmp     al, -9
247
        jle     @f
247
        jle     @f
248
        dec     eax
248
        dec     eax
249
        js      .no
249
        js      .no
250
        test    [ebx+0x44], al
250
        test    [ebx+0x44], al
251
        jnz     .no
251
        jnz     .no
252
@@:         ; OK, this is correct NTFS bootsector
252
@@:         ; OK, this is correct NTFS bootsector
253
        clc
253
        clc
254
        ret
254
        ret
255
.no:        ; No, this bootsector isn't NTFS
255
.no:        ; No, this bootsector isn't NTFS
256
        stc
256
        stc
257
        ret
257
        ret
258
 
258
 
259
; Mount if it's a valid NTFS partition.
259
; Mount if it's a valid NTFS partition.
260
ntfs_create_partition:
260
ntfs_create_partition:
261
;   in:
261
;   in:
262
; ebp -> PARTITION structure
262
; ebp -> PARTITION structure
263
; ebx -> boot sector
263
; ebx -> boot sector
264
; ebx+512 -> buffer
264
; ebx+512 -> buffer
265
;   out:
265
;   out:
266
; eax -> NTFS structure, 0 = not NTFS
266
; eax -> NTFS structure, 0 = not NTFS
267
        cmp     dword [esi+DISK.MediaInfo.SectorSize], 512
267
        cmp     dword [esi+DISK.MediaInfo.SectorSize], 512
268
        jnz     .nope
268
        jnz     .nope
269
        mov     edx, dword [ebp+PARTITION.Length]
269
        mov     edx, dword [ebp+PARTITION.Length]
270
        cmp     dword [esp+4], 0
270
        cmp     dword [esp+4], 0
271
        jz      .boot_read_ok
271
        jz      .boot_read_ok
272
        add     ebx, 512
272
        add     ebx, 512
273
        lea     eax, [edx-1]
273
        lea     eax, [edx-1]
274
        call    fs_read32_sys
274
        call    fs_read32_sys
275
        test    eax, eax
275
        test    eax, eax
276
        jnz     @f
276
        jnz     @f
277
        call    ntfs_test_bootsec
277
        call    ntfs_test_bootsec
278
        jnc     .ntfs_setup
278
        jnc     .ntfs_setup
279
@@:
279
@@:
280
        mov     eax, edx
280
        mov     eax, edx
281
        shr     eax, 1
281
        shr     eax, 1
282
        call    fs_read32_sys
282
        call    fs_read32_sys
283
        test    eax, eax
283
        test    eax, eax
284
        jnz     .nope
284
        jnz     .nope
285
.boot_read_ok:
285
.boot_read_ok:
286
        call    ntfs_test_bootsec
286
        call    ntfs_test_bootsec
287
        jnc     .ntfs_setup
287
        jnc     .ntfs_setup
288
.nope:
288
.nope:
289
        xor     eax, eax
289
        xor     eax, eax
290
        jmp     .exit
290
        jmp     .exit
291
 
291
 
292
.ntfs_setup:    ; By given bootsector, initialize some NTFS variables
292
.ntfs_setup:    ; By given bootsector, initialize some NTFS variables
293
        stdcall kernel_alloc, 1000h
293
        stdcall kernel_alloc, 1000h
294
        test    eax, eax
294
        test    eax, eax
295
        jz      .exit
295
        jz      .exit
296
        mov     ecx, dword [ebp+PARTITION.FirstSector]
296
        mov     ecx, dword [ebp+PARTITION.FirstSector]
297
        mov     dword [eax+NTFS.FirstSector], ecx
297
        mov     dword [eax+NTFS.FirstSector], ecx
298
        mov     ecx, dword [ebp+PARTITION.FirstSector+4]
298
        mov     ecx, dword [ebp+PARTITION.FirstSector+4]
299
        mov     dword [eax+NTFS.FirstSector+4], ecx
299
        mov     dword [eax+NTFS.FirstSector+4], ecx
300
        mov     ecx, [ebp+PARTITION.Disk]
300
        mov     ecx, [ebp+PARTITION.Disk]
301
        mov     [eax+NTFS.Disk], ecx
301
        mov     [eax+NTFS.Disk], ecx
302
        mov     [eax+NTFS.FSUserFunctions], ntfs_user_functions
302
        mov     [eax+NTFS.FSUserFunctions], ntfs_user_functions
303
        mov     [eax+NTFS.bWriteAttr], 0
303
        mov     [eax+NTFS.bWriteAttr], 0
304
 
304
 
305
        push    ebx ebp esi
305
        push    ebx ebp esi
306
        mov     ebp, eax
306
        mov     ebp, eax
307
        lea     ecx, [ebp+NTFS.Lock]
307
        lea     ecx, [ebp+NTFS.Lock]
308
        call    mutex_init
308
        call    mutex_init
309
        movzx   eax, byte [ebx+13]
309
        movzx   eax, byte [ebx+13]
310
        mov     [ebp+NTFS.sectors_per_cluster], eax
310
        mov     [ebp+NTFS.sectors_per_cluster], eax
311
        mov     eax, [ebx+0x28]
311
        mov     eax, [ebx+0x28]
312
        mov     dword [ebp+NTFS.Length], eax
312
        mov     dword [ebp+NTFS.Length], eax
313
        and     dword [ebp+NTFS.Length+4], 0
313
        and     dword [ebp+NTFS.Length+4], 0
314
        mov     eax, [ebx+0x30]
314
        mov     eax, [ebx+0x30]
315
        mov     [ebp+NTFS.mft_cluster], eax
315
        mov     [ebp+NTFS.mft_cluster], eax
316
        mov     eax, [ebx+0x38]
316
        mov     eax, [ebx+0x38]
317
        mov     [ebp+NTFS.mftmirr_cluster], eax
317
        mov     [ebp+NTFS.mftmirr_cluster], eax
318
        movsx   eax, byte [ebx+0x40]
318
        movsx   eax, byte [ebx+0x40]
319
        test    eax, eax
319
        test    eax, eax
320
        js      @f
320
        js      @f
321
        mul     [ebp+NTFS.sectors_per_cluster]
321
        mul     [ebp+NTFS.sectors_per_cluster]
322
        shl     eax, 9
322
        shl     eax, 9
323
        jmp     .1
323
        jmp     .1
324
 
324
 
325
@@:
325
@@:
326
        neg     eax
326
        neg     eax
327
        mov     ecx, eax
327
        mov     ecx, eax
328
        mov     eax, 1
328
        mov     eax, 1
329
        shl     eax, cl
329
        shl     eax, cl
330
.1:
330
.1:
331
        mov     [ebp+NTFS.frs_size], eax
331
        mov     [ebp+NTFS.frs_size], eax
332
        stdcall kernel_alloc, eax
332
        stdcall kernel_alloc, eax
333
        test    eax, eax
333
        test    eax, eax
334
        jz      .fail_free
334
        jz      .fail_free
335
        mov     [ebp+NTFS.frs_buffer], eax
335
        mov     [ebp+NTFS.frs_buffer], eax
336
; read $MFT disposition
336
; read $MFT disposition
337
        mov     eax, [ebp+NTFS.mft_cluster]
337
        mov     eax, [ebp+NTFS.mft_cluster]
338
        mul     [ebp+NTFS.sectors_per_cluster]
338
        mul     [ebp+NTFS.sectors_per_cluster]
339
        mov     ecx, [ebp+NTFS.frs_size]
339
        mov     ecx, [ebp+NTFS.frs_size]
340
        shr     ecx, 9
340
        shr     ecx, 9
341
        mov     ebx, [ebp+NTFS.frs_buffer]
341
        mov     ebx, [ebp+NTFS.frs_buffer]
342
        call    fs_read64_sys
342
        call    fs_read64_sys
343
        test    eax, eax
343
        test    eax, eax
344
        jnz     .usemirr
344
        jnz     .usemirr
345
        cmp     dword [ebx], 'FILE'
345
        cmp     dword [ebx], 'FILE'
346
        jnz     .usemirr
346
        jnz     .usemirr
347
        call    ntfs_restore_usa_frs
347
        call    ntfs_restore_usa_frs
348
        jnc     .mftok
348
        jnc     .mftok
349
.usemirr:
349
.usemirr:
350
        mov     eax, [ebp+NTFS.mftmirr_cluster]
350
        mov     eax, [ebp+NTFS.mftmirr_cluster]
351
        mul     [ebp+NTFS.sectors_per_cluster]
351
        mul     [ebp+NTFS.sectors_per_cluster]
352
        mov     ecx, [ebp+NTFS.frs_size]
352
        mov     ecx, [ebp+NTFS.frs_size]
353
        shr     ecx, 9
353
        shr     ecx, 9
354
        mov     ebx, [ebp+NTFS.frs_buffer]
354
        mov     ebx, [ebp+NTFS.frs_buffer]
355
        call    fs_read64_sys
355
        call    fs_read64_sys
356
        test    eax, eax
356
        test    eax, eax
357
        jnz     .fail_free_frs
357
        jnz     .fail_free_frs
358
        cmp     dword [ebx], 'FILE'
358
        cmp     dword [ebx], 'FILE'
359
        jnz     .fail_free_frs
359
        jnz     .fail_free_frs
360
        call    ntfs_restore_usa_frs
360
        call    ntfs_restore_usa_frs
361
        jc      .fail_free_frs
361
        jc      .fail_free_frs
362
.mftok:     ; prepare $MFT retrieval information
362
.mftok:     ; prepare $MFT retrieval information
363
; search for unnamed non-resident $DATA attribute
363
; search for unnamed non-resident $DATA attribute
364
        movzx   eax, word [ebx+attributeOffset]
364
        movzx   eax, word [ebx+attributeOffset]
365
        add     eax, ebx
365
        add     eax, ebx
366
.scandata:
366
.scandata:
367
        cmp     dword [eax], -1
367
        cmp     dword [eax], -1
368
        jz      .fail_free_frs
368
        jz      .fail_free_frs
369
        cmp     dword [eax], 0x80
369
        cmp     dword [eax], 0x80
370
        jnz     @f
370
        jnz     @f
371
        cmp     byte [eax+nameLength], 0
371
        cmp     byte [eax+nameLength], 0
372
        jz      .founddata
372
        jz      .founddata
373
@@:
373
@@:
374
        add     eax, [eax+sizeWithHeader]
374
        add     eax, [eax+sizeWithHeader]
375
        jmp     .scandata
375
        jmp     .scandata
376
 
376
 
377
.founddata:
377
.founddata:
378
        cmp     byte [eax+nonResidentFlag], 0
378
        cmp     byte [eax+nonResidentFlag], 0
379
        jz      .fail_free_frs
379
        jz      .fail_free_frs
380
        movzx   esi, word [eax+dataRunsOffset]
380
        movzx   esi, word [eax+dataRunsOffset]
381
        add     esi, eax
381
        add     esi, eax
382
        mov     edx, [eax+attributeAllocatedSize+4]
382
        mov     edx, [eax+attributeAllocatedSize+4]
383
        mov     eax, [eax+attributeAllocatedSize]
383
        mov     eax, [eax+attributeAllocatedSize]
384
        shrd    eax, edx, 9
384
        shrd    eax, edx, 9
385
        mov     [ebp+NTFS.mftSize], eax
385
        mov     [ebp+NTFS.mftSize], eax
386
        sub     esp, 10h
386
        sub     esp, 10h
387
        lea     ecx, [ebp+NTFS.mft_retrieval]
387
        lea     ecx, [ebp+NTFS.mft_retrieval]
388
        xor     edx, edx
388
        xor     edx, edx
389
.scanmcb:   ; load descriptions of fragments
389
.scanmcb:   ; load descriptions of fragments
390
        call    ntfs_decode_mcb_entry
390
        call    ntfs_decode_mcb_entry
391
        jnc     .scanmcbend
391
        jnc     .scanmcbend
392
        mov     eax, [esp]      ; block length
392
        mov     eax, [esp]      ; block length
393
        mov     [ecx], eax
393
        mov     [ecx], eax
394
        add     edx, [esp+8]    ; block addr
394
        add     edx, [esp+8]    ; block addr
395
        mov     [ecx+4], edx
395
        mov     [ecx+4], edx
396
        add     ecx, 8
396
        add     ecx, 8
397
        jmp     .scanmcb
397
        jmp     .scanmcb
398
 
398
 
399
.scanmcbend:
399
.scanmcbend:
400
        add     esp, 10h
400
        add     esp, 10h
401
        lea     eax, [ebp+NTFS.attrlist_buf]
401
        lea     eax, [ebp+NTFS.attrlist_buf]
402
        cmp     eax, ecx
402
        cmp     eax, ecx
403
        jc      @f
403
        jc      @f
404
        mov     eax, ecx
404
        mov     eax, ecx
405
@@:
405
@@:
406
        mov     [ebp+NTFS.mft_retrieval_end], eax
406
        mov     [ebp+NTFS.mft_retrieval_end], eax
407
; allocate index buffers
407
; allocate index buffers
408
        stdcall kernel_alloc, 2000h
408
        stdcall kernel_alloc, 2000h
409
        test    eax, eax
409
        test    eax, eax
410
        jz      .fail_free_frs
410
        jz      .fail_free_frs
411
        mov     [ebp+NTFS.cur_index_buf], eax
411
        mov     [ebp+NTFS.cur_index_buf], eax
412
        add     eax, 1000h
412
        add     eax, 1000h
413
        mov     [ebp+NTFS.secondIndexBuffer], eax
413
        mov     [ebp+NTFS.secondIndexBuffer], eax
414
        mov     [ebp+NTFS.cur_index_size], 8
414
        mov     [ebp+NTFS.cur_index_size], 8
415
; reserve adress space for bitmap buffer and load some part of bitmap
415
; reserve adress space for bitmap buffer and load some part of bitmap
416
        mov     eax, dword [ebp+NTFS.Length]
416
        mov     eax, dword [ebp+NTFS.Length]
417
        xor     edx, edx
417
        xor     edx, edx
418
        div     [ebp+NTFS.sectors_per_cluster]
418
        div     [ebp+NTFS.sectors_per_cluster]
419
        shr     eax, 3
419
        shr     eax, 3
420
        mov     [ebp+NTFS.BitmapTotalSize], eax
420
        mov     [ebp+NTFS.BitmapTotalSize], eax
421
        add     eax, 7FFFh
421
        add     eax, 7FFFh
422
        and     eax, not 7FFFh
422
        and     eax, not 7FFFh
423
        push    eax
423
        push    eax
424
        call    alloc_kernel_space
424
        call    alloc_kernel_space
425
        test    eax, eax
425
        test    eax, eax
426
        jz      .failFreeIndex
426
        jz      .failFreeIndex
427
        mov     [ebp+NTFS.BitmapBuffer], eax
427
        mov     [ebp+NTFS.BitmapBuffer], eax
428
        mov     [ebp+NTFS.cur_buf], eax
428
        mov     [ebp+NTFS.cur_buf], eax
429
        mov     eax, [ebp+NTFS.BitmapTotalSize]
429
        mov     eax, [ebp+NTFS.BitmapTotalSize]
430
        add     eax, [ebp+NTFS.mft_cluster]
430
        add     eax, [ebp+NTFS.mft_cluster]
431
        shr     eax, 3+2        ; reserve 1/8 of partition for $MFT
431
        shr     eax, 3+2        ; reserve 1/8 of partition for $MFT
432
        shl     eax, 2
432
        shl     eax, 2
433
        mov     [ebp+NTFS.BitmapStart], eax
433
        mov     [ebp+NTFS.BitmapStart], eax
434
        shr     eax, 15
434
        shr     eax, 15
435
        inc     eax
435
        inc     eax
436
        shl     eax, 3
436
        shl     eax, 3
437
        push    eax
437
        push    eax
438
        push    eax
438
        push    eax
439
        shl     eax, 3
439
        shl     eax, 3
440
        mov     [ebp+NTFS.cur_size], eax
440
        mov     [ebp+NTFS.cur_size], eax
441
        call    alloc_pages
441
        call    alloc_pages
442
        test    eax, eax
442
        test    eax, eax
443
        pop     ecx
443
        pop     ecx
444
        jz      .failFreeBitmap
444
        jz      .failFreeBitmap
445
        add     eax, 3
445
        add     eax, 3
446
        mov     ebx, [ebp+NTFS.BitmapBuffer]
446
        mov     ebx, [ebp+NTFS.BitmapBuffer]
447
        call    commit_pages
447
        call    commit_pages
448
        mov     [ebp+NTFS.cur_iRecord], 6
448
        mov     [ebp+NTFS.cur_iRecord], 6
449
        mov     [ebp+NTFS.cur_attr], 0x80
449
        mov     [ebp+NTFS.cur_attr], 0x80
450
        mov     [ebp+NTFS.cur_offs], 0
450
        mov     [ebp+NTFS.cur_offs], 0
451
        call    ntfs_read_attr
451
        call    ntfs_read_attr
452
        jc      .failFreeBitmap
452
        jc      .failFreeBitmap
453
        mov     eax, [ebp+NTFS.cur_read]
453
        mov     eax, [ebp+NTFS.cur_read]
454
        mov     [ebp+NTFS.BitmapSize], eax
454
        mov     [ebp+NTFS.BitmapSize], eax
455
        mov     eax, [ebp+NTFS.LastRead]
455
        mov     eax, [ebp+NTFS.LastRead]
456
        mov     [ebp+NTFS.BitmapLocation], eax
456
        mov     [ebp+NTFS.BitmapLocation], eax
457
; read MFT $BITMAP attribute
457
; read MFT $BITMAP attribute
458
        mov     eax, [ebp+NTFS.sectors_per_cluster]
458
        mov     eax, [ebp+NTFS.sectors_per_cluster]
459
        mov     [ebp+NTFS.cur_size], eax
459
        mov     [ebp+NTFS.cur_size], eax
460
        shl     eax, 9
460
        shl     eax, 9
461
        stdcall kernel_alloc, eax
461
        stdcall kernel_alloc, eax
462
        test    eax, eax
462
        test    eax, eax
463
        jz      .failFreeBitmap
463
        jz      .failFreeBitmap
464
        mov     [ebp+NTFS.mftBitmapBuffer], eax
464
        mov     [ebp+NTFS.mftBitmapBuffer], eax
465
        mov     [ebp+NTFS.cur_buf], eax
465
        mov     [ebp+NTFS.cur_buf], eax
466
        mov     [ebp+NTFS.cur_iRecord], 0
466
        mov     [ebp+NTFS.cur_iRecord], 0
467
        mov     [ebp+NTFS.cur_attr], 0xB0
467
        mov     [ebp+NTFS.cur_attr], 0xB0
468
        mov     [ebp+NTFS.cur_offs], 0
468
        mov     [ebp+NTFS.cur_offs], 0
469
        call    ntfs_read_attr
469
        call    ntfs_read_attr
470
        mov     eax, [ebp+NTFS.cur_read]
470
        mov     eax, [ebp+NTFS.cur_read]
471
        cmp     eax, 4
471
        cmp     eax, 4
472
        jc      .failFreeBitmapMFT
472
        jc      .failFreeBitmapMFT
473
        mov     ecx, [ebp+NTFS.attr_offs]
473
        mov     ecx, [ebp+NTFS.attr_offs]
474
        cmp     byte [ecx+nonResidentFlag], 1
474
        cmp     byte [ecx+nonResidentFlag], 1
475
        jnz     .failFreeBitmapMFT
475
        jnz     .failFreeBitmapMFT
476
        mov     [ebp+NTFS.mftBitmapSize], eax
476
        mov     [ebp+NTFS.mftBitmapSize], eax
477
        mov     eax, [ebp+NTFS.LastRead]
477
        mov     eax, [ebp+NTFS.LastRead]
478
        mov     [ebp+NTFS.mftBitmapLocation], eax
478
        mov     [ebp+NTFS.mftBitmapLocation], eax
479
 
479
 
480
        mov     eax, ebp
480
        mov     eax, ebp
481
.pop_exit:
481
.pop_exit:
482
        pop     esi ebp ebx
482
        pop     esi ebp ebx
483
.exit:
483
.exit:
484
        cmp     dword [esp+4], 0
484
        cmp     dword [esp+4], 0
485
        jz      @f
485
        jz      @f
486
        sub     ebx, 512
486
        sub     ebx, 512
487
@@:
487
@@:
488
        ret
488
        ret
489
 
489
 
490
.failFreeBitmapMFT:
490
.failFreeBitmapMFT:
491
        stdcall kernel_free, [ebp+NTFS.mftBitmapBuffer]
491
        stdcall kernel_free, [ebp+NTFS.mftBitmapBuffer]
492
.failFreeBitmap:
492
.failFreeBitmap:
493
        stdcall kernel_free, [ebp+NTFS.BitmapBuffer]
493
        stdcall kernel_free, [ebp+NTFS.BitmapBuffer]
494
.failFreeIndex:
494
.failFreeIndex:
495
        mov     eax, [ebp+NTFS.cur_index_buf]
495
        mov     eax, [ebp+NTFS.cur_index_buf]
496
        cmp     eax, [ebp+NTFS.secondIndexBuffer]
496
        cmp     eax, [ebp+NTFS.secondIndexBuffer]
497
        jc      @f
497
        jc      @f
498
        mov     eax, [ebp+NTFS.secondIndexBuffer]
498
        mov     eax, [ebp+NTFS.secondIndexBuffer]
499
@@:
499
@@:
500
        stdcall kernel_free, eax
500
        stdcall kernel_free, eax
501
.fail_free_frs:
501
.fail_free_frs:
502
        stdcall kernel_free, [ebp+NTFS.frs_buffer]
502
        stdcall kernel_free, [ebp+NTFS.frs_buffer]
503
.fail_free:
503
.fail_free:
504
        stdcall kernel_free, ebp
504
        stdcall kernel_free, ebp
505
        xor     eax, eax
505
        xor     eax, eax
506
        jmp     .pop_exit
506
        jmp     .pop_exit
507
 
507
 
508
ntfs_free:
508
ntfs_free:
509
        push    ebx
509
        push    ebx
510
        mov     ebx, eax
510
        mov     ebx, eax
511
        stdcall kernel_free, [ebx+NTFS.frs_buffer]
511
        stdcall kernel_free, [ebx+NTFS.frs_buffer]
512
        stdcall kernel_free, [ebx+NTFS.mftBitmapBuffer]
512
        stdcall kernel_free, [ebx+NTFS.mftBitmapBuffer]
513
        stdcall kernel_free, [ebx+NTFS.BitmapBuffer]
513
        stdcall kernel_free, [ebx+NTFS.BitmapBuffer]
514
        mov     eax, [ebx+NTFS.cur_index_buf]
514
        mov     eax, [ebx+NTFS.cur_index_buf]
515
        cmp     eax, [ebx+NTFS.secondIndexBuffer]
515
        cmp     eax, [ebx+NTFS.secondIndexBuffer]
516
        jc      @f
516
        jc      @f
517
        mov     eax, [ebx+NTFS.secondIndexBuffer]
517
        mov     eax, [ebx+NTFS.secondIndexBuffer]
518
@@:
518
@@:
519
        stdcall kernel_free, eax
519
        stdcall kernel_free, eax
520
        stdcall kernel_free, ebx
520
        stdcall kernel_free, ebx
521
        pop     ebx
521
        pop     ebx
522
        ret
522
        ret
523
 
523
 
524
ntfs_lock:
524
ntfs_lock:
525
        lea     ecx, [ebp+NTFS.Lock]
525
        lea     ecx, [ebp+NTFS.Lock]
526
        jmp     mutex_lock
526
        jmp     mutex_lock
527
 
527
 
528
ntfs_unlock:
528
ntfs_unlock:
529
        lea     ecx, [ebp+NTFS.Lock]
529
        lea     ecx, [ebp+NTFS.Lock]
530
        jmp     mutex_unlock
530
        jmp     mutex_unlock
531
 
531
 
532
ntfs_read_attr:
532
ntfs_read_attr:
533
; [ebp+NTFS.bWriteAttr]=1 -> write attribute
533
; [ebp+NTFS.bWriteAttr]=1 -> write attribute
534
;   in:
534
;   in:
535
; [ebp+NTFS.cur_iRecord] = number of fileRecord
535
; [ebp+NTFS.cur_iRecord] = number of fileRecord
536
; [ebp+NTFS.cur_attr] = attribute type
536
; [ebp+NTFS.cur_attr] = attribute type
537
; [ebp+NTFS.cur_offs] = attribute VCN in sectors
537
; [ebp+NTFS.cur_offs] = attribute VCN in sectors
538
; [ebp+NTFS.cur_buf] -> buffer for data
538
; [ebp+NTFS.cur_buf] -> buffer for data
539
; [ebp+NTFS.cur_size] = max sectors to read
539
; [ebp+NTFS.cur_size] = max sectors to read
540
;   out:
540
;   out:
541
; [ebp+NTFS.cur_read] = bytes readen
541
; [ebp+NTFS.cur_read] = bytes readen
542
; CF=1 -> failed, eax = disk error code, eax=0 -> something with FS
542
; CF=1 -> failed, eax = disk error code, eax=0 -> something with FS
543
        xor     eax, eax
543
        xor     eax, eax
544
        pushad
544
        pushad
545
        and     [ebp+NTFS.cur_read], 0
545
        and     [ebp+NTFS.cur_read], 0
546
        cmp     [ebp+NTFS.cur_iRecord], 0
546
        cmp     [ebp+NTFS.cur_iRecord], 0
547
        jnz     .nomft
547
        jnz     .nomft
548
        cmp     [ebp+NTFS.cur_attr], 0x80
548
        cmp     [ebp+NTFS.cur_attr], 0x80
549
        jnz     .nomft
549
        jnz     .nomft
550
; precalculated part of $Mft $DATA
550
; precalculated part of $Mft $DATA
551
        mov     eax, [ebp+NTFS.cur_offs]
551
        mov     eax, [ebp+NTFS.cur_offs]
552
        xor     edx, edx
552
        xor     edx, edx
553
        div     [ebp+NTFS.sectors_per_cluster]
553
        div     [ebp+NTFS.sectors_per_cluster]
554
        mov     ebx, edx
554
        mov     ebx, edx
555
        mov     [ebp+NTFS.fragmentCount], 0
555
        mov     [ebp+NTFS.fragmentCount], 0
556
; eax = VCN, ebx = offset in sectors from beginning of cluster
556
; eax = VCN, ebx = offset in sectors from beginning of cluster
557
        lea     esi, [ebp+NTFS.mft_retrieval]
557
        lea     esi, [ebp+NTFS.mft_retrieval]
558
        sub     esi, 8
558
        sub     esi, 8
559
.mftscan:
559
.mftscan:
560
        add     esi, 8
560
        add     esi, 8
561
        cmp     esi, [ebp+NTFS.mft_retrieval_end]
561
        cmp     esi, [ebp+NTFS.mft_retrieval_end]
562
        jz      .nomft
562
        jz      .nomft
563
        mov     ecx, [esi+4]
563
        mov     ecx, [esi+4]
564
        sub     eax, [esi]
564
        sub     eax, [esi]
565
        jnc     .mftscan
565
        jnc     .mftscan
566
        add     ecx, eax
566
        add     ecx, eax
567
        add     ecx, [esi]
567
        add     ecx, [esi]
568
        neg     eax
568
        neg     eax
569
        mul     [ebp+NTFS.sectors_per_cluster]
569
        mul     [ebp+NTFS.sectors_per_cluster]
570
        xchg    eax, ecx
570
        xchg    eax, ecx
571
        mul     [ebp+NTFS.sectors_per_cluster]
571
        mul     [ebp+NTFS.sectors_per_cluster]
572
        sub     ecx, ebx
572
        sub     ecx, ebx
573
        add     eax, ebx
573
        add     eax, ebx
574
        mov     ebx, [ebp+NTFS.cur_buf]
574
        mov     ebx, [ebp+NTFS.cur_buf]
575
        cmp     ecx, [ebp+NTFS.cur_size]
575
        cmp     ecx, [ebp+NTFS.cur_size]
576
        jb      @f
576
        jb      @f
577
        mov     ecx, [ebp+NTFS.cur_size]
577
        mov     ecx, [ebp+NTFS.cur_size]
578
@@:
578
@@:
579
        mov     [ebp+NTFS.LastRead], eax
579
        mov     [ebp+NTFS.LastRead], eax
580
        mov     edi, ecx
580
        mov     edi, ecx
581
        call    fs_read64_sys
581
        call    fs_read64_sys
582
        test    eax, eax
582
        test    eax, eax
583
        jnz     .errret
583
        jnz     .errret
584
        sub     [ebp+NTFS.cur_size], edi
584
        sub     [ebp+NTFS.cur_size], edi
585
        add     [ebp+NTFS.cur_offs], edi
585
        add     [ebp+NTFS.cur_offs], edi
586
        shl     edi, 9
586
        shl     edi, 9
587
        add     [ebp+NTFS.cur_read], edi
587
        add     [ebp+NTFS.cur_read], edi
588
        add     [ebp+NTFS.cur_buf], edi
588
        add     [ebp+NTFS.cur_buf], edi
589
        inc     [ebp+NTFS.fragmentCount]
589
        inc     [ebp+NTFS.fragmentCount]
590
        xor     eax, eax
590
        xor     eax, eax
591
        xor     ebx, ebx
591
        xor     ebx, ebx
592
        cmp     [ebp+NTFS.cur_size], eax
592
        cmp     [ebp+NTFS.cur_size], eax
593
        jz      @f
593
        jz      @f
594
        jmp     .mftscan
594
        jmp     .mftscan
595
 
595
 
596
.errret2_pop:
596
.errret2_pop:
597
        xor     eax, eax
597
        xor     eax, eax
598
.errret_pop:
598
.errret_pop:
599
        pop     ecx
599
        pop     ecx
600
        pop     ecx
600
        pop     ecx
601
.errret:
601
.errret:
602
        mov     [esp+28], eax
602
        mov     [esp+28], eax
603
        stc
603
        stc
604
@@:
604
@@:
605
        popad
605
        popad
606
        ret
606
        ret
607
 
607
 
608
.nomft:
608
.nomft:
609
; 1. Read file record.
609
; 1. Read file record.
610
; N.B. This will do recursive call of read_attr for $MFT::$Data.
610
; N.B. This will do recursive call of read_attr for $MFT::$Data.
611
        mov     eax, [ebp+NTFS.cur_iRecord]
611
        mov     eax, [ebp+NTFS.cur_iRecord]
612
        and     [ebp+NTFS.attr_list], 0
612
        and     [ebp+NTFS.attr_list], 0
613
        or      dword [ebp+NTFS.attr_size+4], -1
613
        or      dword [ebp+NTFS.attr_size+4], -1
614
        or      [ebp+NTFS.attr_iBaseRecord], -1
614
        or      [ebp+NTFS.attr_iBaseRecord], -1
615
        call    ntfs_read_file_record
615
        call    ntfs_read_file_record
616
        jc      .errret
616
        jc      .errret
617
; 2. Find required attribute.
617
; 2. Find required attribute.
618
        mov     eax, [ebp+NTFS.frs_buffer]
618
        mov     eax, [ebp+NTFS.frs_buffer]
619
; a) For auxiliary records, read base record.
619
; a) For auxiliary records, read base record.
620
; If base record is present, base iRecord may be 0 (for $Mft),
620
; If base record is present, base iRecord may be 0 (for $Mft),
621
; but SequenceNumber is nonzero.
621
; but SequenceNumber is nonzero.
622
        cmp     word [eax+baseRecordReuse], 0
622
        cmp     word [eax+baseRecordReuse], 0
623
        jz      @f
623
        jz      @f
624
        mov     eax, [eax+baseRecordReference]
624
        mov     eax, [eax+baseRecordReference]
625
.beginfindattr:
625
.beginfindattr:
626
        call    ntfs_read_file_record
626
        call    ntfs_read_file_record
627
        jc      .errret
627
        jc      .errret
628
        jmp     @f
628
        jmp     @f
629
 
629
 
630
.newAttribute:
630
.newAttribute:
631
        pushad
631
        pushad
632
        and     [ebp+NTFS.cur_read], 0
632
        and     [ebp+NTFS.cur_read], 0
633
@@:
633
@@:
634
; b) Scan for required attribute and for $ATTR_LIST
634
; b) Scan for required attribute and for $ATTR_LIST
635
        mov     eax, [ebp+NTFS.frs_buffer]
635
        mov     eax, [ebp+NTFS.frs_buffer]
636
        movzx   ecx, word [eax+attributeOffset]
636
        movzx   ecx, word [eax+attributeOffset]
637
        add     eax, ecx
637
        add     eax, ecx
638
        mov     ecx, [ebp+NTFS.cur_attr]
638
        mov     ecx, [ebp+NTFS.cur_attr]
639
        and     [ebp+NTFS.attr_offs], 0
639
        and     [ebp+NTFS.attr_offs], 0
640
.scanattr:
640
.scanattr:
641
        cmp     dword [eax], -1
641
        cmp     dword [eax], -1
642
        jz      .scandone
642
        jz      .scandone
643
        cmp     dword [eax], ecx
643
        cmp     dword [eax], ecx
644
        jz      .okattr
644
        jz      .okattr
645
        cmp     [ebp+NTFS.attr_iBaseRecord], -1
645
        cmp     [ebp+NTFS.attr_iBaseRecord], -1
646
        jnz     .scancont
646
        jnz     .scancont
647
        cmp     dword [eax], 0x20       ; $ATTR_LIST
647
        cmp     dword [eax], 0x20       ; $ATTR_LIST
648
        jnz     .scancont
648
        jnz     .scancont
649
        mov     [ebp+NTFS.attr_list], eax
649
        mov     [ebp+NTFS.attr_list], eax
650
        jmp     .scancont
650
        jmp     .scancont
651
 
651
 
652
.okattr:
652
.okattr:
653
; ignore named $DATA attributes (aka NTFS streams)
653
; ignore named $DATA attributes (aka NTFS streams)
654
        cmp     ecx, 0x80
654
        cmp     ecx, 0x80
655
        jnz     @f
655
        jnz     @f
656
        cmp     byte [eax+nameLength], 0
656
        cmp     byte [eax+nameLength], 0
657
        jnz     .scancont
657
        jnz     .scancont
658
@@:
658
@@:
659
        mov     [ebp+NTFS.attr_offs], eax
659
        mov     [ebp+NTFS.attr_offs], eax
660
.scancont:
660
.scancont:
661
        add     eax, [eax+sizeWithHeader]
661
        add     eax, [eax+sizeWithHeader]
662
        jmp     .scanattr
662
        jmp     .scanattr
663
 
663
 
664
.continue:
664
.continue:
665
        pushad
665
        pushad
666
        and     [ebp+NTFS.cur_read], 0
666
        and     [ebp+NTFS.cur_read], 0
667
.scandone:
667
.scandone:
668
; c) Check for required offset and length
668
; c) Check for required offset and length
669
        mov     ecx, [ebp+NTFS.attr_offs]
669
        mov     ecx, [ebp+NTFS.attr_offs]
670
        jecxz   .noattr
670
        jecxz   .noattr
671
        push    [ebp+NTFS.cur_size]
671
        push    [ebp+NTFS.cur_size]
672
        push    [ebp+NTFS.cur_read]
672
        push    [ebp+NTFS.cur_read]
673
        call    .doreadattr
673
        call    .doreadattr
674
        pop     edx
674
        pop     edx
675
        pop     ecx
675
        pop     ecx
676
        jc      .ret
676
        jc      .ret
677
        cmp     [ebp+NTFS.bCanContinue], 0
677
        cmp     [ebp+NTFS.bCanContinue], 0
678
        jz      .ret
678
        jz      .ret
679
        sub     edx, [ebp+NTFS.cur_read]
679
        sub     edx, [ebp+NTFS.cur_read]
680
        neg     edx
680
        neg     edx
681
        shr     edx, 9
681
        shr     edx, 9
682
        sub     ecx, edx
682
        sub     ecx, edx
683
        mov     [ebp+NTFS.cur_size], ecx
683
        mov     [ebp+NTFS.cur_size], ecx
684
        jz      .ret
684
        jz      .ret
685
.noattr:
685
.noattr:
686
        cmp     [ebp+NTFS.cur_attr], 0x20
686
        cmp     [ebp+NTFS.cur_attr], 0x20
687
        jz      @f
687
        jz      @f
688
        mov     ecx, [ebp+NTFS.attr_list]
688
        mov     ecx, [ebp+NTFS.attr_list]
689
        test    ecx, ecx
689
        test    ecx, ecx
690
        jnz     .lookattr
690
        jnz     .lookattr
691
        and     dword [esp+28], 0
691
        and     dword [esp+28], 0
692
        cmp     [ebp+NTFS.attr_offs], 1     ; define CF
692
        cmp     [ebp+NTFS.attr_offs], 1     ; define CF
693
.ret:
693
.ret:
694
        popad
694
        popad
695
        ret
695
        ret
696
 
696
 
697
.lookattr:
697
.lookattr:
698
; required attribute or required offset was not found in base record;
698
; required attribute or required offset was not found in base record;
699
; it may be present in auxiliary records;
699
; it may be present in auxiliary records;
700
; scan $ATTR_LIST
700
; scan $ATTR_LIST
701
        mov     eax, [ebp+NTFS.attr_iBaseRecord]
701
        mov     eax, [ebp+NTFS.attr_iBaseRecord]
702
        cmp     eax, -1
702
        cmp     eax, -1
703
        jz      @f
703
        jz      @f
704
        call    ntfs_read_file_record
704
        call    ntfs_read_file_record
705
        jc      .errret
705
        jc      .errret
706
        or      [ebp+NTFS.attr_iBaseRecord], -1
706
        or      [ebp+NTFS.attr_iBaseRecord], -1
707
@@:
707
@@:
708
        push    [ebp+NTFS.cur_offs]
708
        push    [ebp+NTFS.cur_offs]
709
        push    [ebp+NTFS.cur_size]
709
        push    [ebp+NTFS.cur_size]
710
        push    [ebp+NTFS.cur_read]
710
        push    [ebp+NTFS.cur_read]
711
        push    [ebp+NTFS.cur_buf]
711
        push    [ebp+NTFS.cur_buf]
712
        push    dword [ebp+NTFS.attr_size]
712
        push    dword [ebp+NTFS.attr_size]
713
        push    dword [ebp+NTFS.attr_size+4]
713
        push    dword [ebp+NTFS.attr_size+4]
714
        or      dword [ebp+NTFS.attr_size+4], -1
714
        or      dword [ebp+NTFS.attr_size+4], -1
715
        and     [ebp+NTFS.cur_offs], 0
715
        and     [ebp+NTFS.cur_offs], 0
716
        mov     [ebp+NTFS.cur_size], 2
716
        mov     [ebp+NTFS.cur_size], 2
717
        and     [ebp+NTFS.cur_read], 0
717
        and     [ebp+NTFS.cur_read], 0
718
        lea     eax, [ebp+NTFS.attrlist_buf]
718
        lea     eax, [ebp+NTFS.attrlist_buf]
719
        cmp     [ebp+NTFS.cur_iRecord], 0
719
        cmp     [ebp+NTFS.cur_iRecord], 0
720
        jnz     @f
720
        jnz     @f
721
        lea     eax, [ebp+NTFS.attrlist_mft_buf]
721
        lea     eax, [ebp+NTFS.attrlist_mft_buf]
722
@@:
722
@@:
723
        mov     [ebp+NTFS.cur_buf], eax
723
        mov     [ebp+NTFS.cur_buf], eax
724
        push    eax
724
        push    eax
725
        call    .doreadattr
725
        call    .doreadattr
726
        pop     esi
726
        pop     esi
727
        mov     edx, 1
727
        mov     edx, 1
728
        pop     dword [ebp+NTFS.attr_size+4]
728
        pop     dword [ebp+NTFS.attr_size+4]
729
        pop     dword [ebp+NTFS.attr_size]
729
        pop     dword [ebp+NTFS.attr_size]
730
        mov     ecx, [ebp+NTFS.cur_read]
730
        mov     ecx, [ebp+NTFS.cur_read]
731
        pop     [ebp+NTFS.cur_buf]
731
        pop     [ebp+NTFS.cur_buf]
732
        pop     [ebp+NTFS.cur_read]
732
        pop     [ebp+NTFS.cur_read]
733
        pop     [ebp+NTFS.cur_size]
733
        pop     [ebp+NTFS.cur_size]
734
        pop     [ebp+NTFS.cur_offs]
734
        pop     [ebp+NTFS.cur_offs]
735
        jc      .errret
735
        jc      .errret
736
        or      edi, -1
736
        or      edi, -1
737
        lea     ecx, [ecx+esi-1Ah]
737
        lea     ecx, [ecx+esi-1Ah]
738
.scanliststart:
738
.scanliststart:
739
        push    ecx
739
        push    ecx
740
        mov     eax, [ebp+NTFS.cur_attr]
740
        mov     eax, [ebp+NTFS.cur_attr]
741
.scanlist:
741
.scanlist:
742
        cmp     esi, [esp]
742
        cmp     esi, [esp]
743
        jae     .scanlistdone
743
        jae     .scanlistdone
744
        cmp     eax, [esi]
744
        cmp     eax, [esi]
745
        jz      @f
745
        jz      @f
746
.scanlistcont:
746
.scanlistcont:
747
        movzx   ecx, word [esi+4]
747
        movzx   ecx, word [esi+4]
748
        add     esi, ecx
748
        add     esi, ecx
749
        jmp     .scanlist
749
        jmp     .scanlist
750
 
750
 
751
@@:
751
@@:
752
; ignore named $DATA attributes (aka NTFS streams)
752
; ignore named $DATA attributes (aka NTFS streams)
753
        cmp     eax, 0x80
753
        cmp     eax, 0x80
754
        jnz     @f
754
        jnz     @f
755
        cmp     byte [esi+6], 0
755
        cmp     byte [esi+6], 0
756
        jnz     .scanlistcont
756
        jnz     .scanlistcont
757
@@:
757
@@:
758
        push    eax
758
        push    eax
759
        mov     eax, [esi+8]
759
        mov     eax, [esi+8]
760
        test    eax, eax
760
        test    eax, eax
761
        jnz     .testf
761
        jnz     .testf
762
        cmp     dword [ebp+NTFS.attr_size+4], -1
762
        cmp     dword [ebp+NTFS.attr_size+4], -1
763
        jnz     .testfz
763
        jnz     .testfz
764
; if attribute is in auxiliary records, its size is defined only in first
764
; if attribute is in auxiliary records, its size is defined only in first
765
        mov     eax, [esi+10h]
765
        mov     eax, [esi+10h]
766
        call    ntfs_read_file_record
766
        call    ntfs_read_file_record
767
        jc      .errret_pop
767
        jc      .errret_pop
768
        mov     eax, [ebp+NTFS.frs_buffer]
768
        mov     eax, [ebp+NTFS.frs_buffer]
769
        movzx   ecx, word [eax+14h]
769
        movzx   ecx, word [eax+14h]
770
        add     eax, ecx
770
        add     eax, ecx
771
        mov     ecx, [ebp+NTFS.cur_attr]
771
        mov     ecx, [ebp+NTFS.cur_attr]
772
@@:
772
@@:
773
        cmp     dword [eax], -1
773
        cmp     dword [eax], -1
774
        jz      .errret2_pop
774
        jz      .errret2_pop
775
        cmp     dword [eax], ecx
775
        cmp     dword [eax], ecx
776
        jz      @f
776
        jz      @f
777
.l1:
777
.l1:
778
        add     eax, [eax+4]
778
        add     eax, [eax+4]
779
        jmp     @b
779
        jmp     @b
780
 
780
 
781
@@:
781
@@:
782
        cmp     eax, 0x80
782
        cmp     eax, 0x80
783
        jnz     @f
783
        jnz     @f
784
        cmp     byte [eax+9], 0
784
        cmp     byte [eax+9], 0
785
        jnz     .l1
785
        jnz     .l1
786
@@:
786
@@:
787
        cmp     byte [eax+8], 0
787
        cmp     byte [eax+8], 0
788
        jnz     .sdnores
788
        jnz     .sdnores
789
        mov     eax, [eax+10h]
789
        mov     eax, [eax+10h]
790
        mov     dword [ebp+NTFS.attr_size], eax
790
        mov     dword [ebp+NTFS.attr_size], eax
791
        and     dword [ebp+NTFS.attr_size+4], 0
791
        and     dword [ebp+NTFS.attr_size+4], 0
792
        jmp     .testfz
792
        jmp     .testfz
793
 
793
 
794
.sdnores:
794
.sdnores:
795
        mov     ecx, [eax+30h]
795
        mov     ecx, [eax+30h]
796
        mov     dword [ebp+NTFS.attr_size], ecx
796
        mov     dword [ebp+NTFS.attr_size], ecx
797
        mov     ecx, [eax+34h]
797
        mov     ecx, [eax+34h]
798
        mov     dword [ebp+NTFS.attr_size+4], ecx
798
        mov     dword [ebp+NTFS.attr_size+4], ecx
799
.testfz:
799
.testfz:
800
        xor     eax, eax
800
        xor     eax, eax
801
.testf:
801
.testf:
802
        imul    eax, [ebp+NTFS.sectors_per_cluster]
802
        imul    eax, [ebp+NTFS.sectors_per_cluster]
803
        cmp     eax, [ebp+NTFS.cur_offs]
803
        cmp     eax, [ebp+NTFS.cur_offs]
804
        pop     eax
804
        pop     eax
805
        ja      @f
805
        ja      @f
806
        mov     edi, [esi+10h]  ; keep previous iRecord
806
        mov     edi, [esi+10h]  ; keep previous iRecord
807
        jmp     .scanlistcont
807
        jmp     .scanlistcont
808
 
808
 
809
@@:
809
@@:
810
        pop     ecx
810
        pop     ecx
811
.scanlistfound:
811
.scanlistfound:
812
        cmp     edi, -1
812
        cmp     edi, -1
813
        jz      .ret
813
        jz      .ret
814
        mov     eax, [ebp+NTFS.cur_iRecord]
814
        mov     eax, [ebp+NTFS.cur_iRecord]
815
        mov     [ebp+NTFS.attr_iBaseRecord], eax
815
        mov     [ebp+NTFS.attr_iBaseRecord], eax
816
        mov     eax, edi
816
        mov     eax, edi
817
        jmp     .beginfindattr
817
        jmp     .beginfindattr
818
 
818
 
819
.scanlistdone:
819
.scanlistdone:
820
        pop     ecx
820
        pop     ecx
821
        sub     ecx, ebp
821
        sub     ecx, ebp
822
        sub     ecx, NTFS.attrlist_buf-1Ah
822
        sub     ecx, NTFS.attrlist_buf-1Ah
823
        cmp     [ebp+NTFS.cur_iRecord], 0
823
        cmp     [ebp+NTFS.cur_iRecord], 0
824
        jnz     @f
824
        jnz     @f
825
        sub     ecx, NTFS.attrlist_mft_buf-NTFS.attrlist_buf
825
        sub     ecx, NTFS.attrlist_mft_buf-NTFS.attrlist_buf
826
@@:
826
@@:
827
        cmp     ecx, 0x400
827
        cmp     ecx, 0x400
828
        jnz     .scanlistfound
828
        jnz     .scanlistfound
829
        inc     edx
829
        inc     edx
830
        push    esi edi
830
        push    esi edi
831
        lea     esi, [ebp+NTFS.attrlist_buf+0x200]
831
        lea     esi, [ebp+NTFS.attrlist_buf+0x200]
832
        lea     edi, [ebp+NTFS.attrlist_buf]
832
        lea     edi, [ebp+NTFS.attrlist_buf]
833
        cmp     [ebp+NTFS.cur_iRecord], 0
833
        cmp     [ebp+NTFS.cur_iRecord], 0
834
        jnz     @f
834
        jnz     @f
835
        lea     esi, [ebp+NTFS.attrlist_mft_buf+0x200]
835
        lea     esi, [ebp+NTFS.attrlist_mft_buf+0x200]
836
        lea     edi, [ebp+NTFS.attrlist_mft_buf]
836
        lea     edi, [ebp+NTFS.attrlist_mft_buf]
837
@@:
837
@@:
838
        mov     ecx, 0x200/4
838
        mov     ecx, 0x200/4
839
        rep movsd
839
        rep movsd
840
        mov     eax, edi
840
        mov     eax, edi
841
        pop     edi esi
841
        pop     edi esi
842
        sub     esi, 0x200
842
        sub     esi, 0x200
843
        push    [ebp+NTFS.cur_offs]
843
        push    [ebp+NTFS.cur_offs]
844
        push    [ebp+NTFS.cur_size]
844
        push    [ebp+NTFS.cur_size]
845
        push    [ebp+NTFS.cur_read]
845
        push    [ebp+NTFS.cur_read]
846
        push    [ebp+NTFS.cur_buf]
846
        push    [ebp+NTFS.cur_buf]
847
        push    dword [ebp+NTFS.attr_size]
847
        push    dword [ebp+NTFS.attr_size]
848
        push    dword [ebp+NTFS.attr_size+4]
848
        push    dword [ebp+NTFS.attr_size+4]
849
        or      dword [ebp+NTFS.attr_size+4], -1
849
        or      dword [ebp+NTFS.attr_size+4], -1
850
        mov     [ebp+NTFS.cur_offs], edx
850
        mov     [ebp+NTFS.cur_offs], edx
851
        mov     [ebp+NTFS.cur_size], 1
851
        mov     [ebp+NTFS.cur_size], 1
852
        and     [ebp+NTFS.cur_read], 0
852
        and     [ebp+NTFS.cur_read], 0
853
        mov     [ebp+NTFS.cur_buf], eax
853
        mov     [ebp+NTFS.cur_buf], eax
854
        mov     ecx, [ebp+NTFS.attr_list]
854
        mov     ecx, [ebp+NTFS.attr_list]
855
        push    esi edx edi
855
        push    esi edx edi
856
        call    .doreadattr
856
        call    .doreadattr
857
        pop     edi edx esi
857
        pop     edi edx esi
858
        mov     ecx, [ebp+NTFS.cur_read]
858
        mov     ecx, [ebp+NTFS.cur_read]
859
        pop     dword [ebp+NTFS.attr_size+4]
859
        pop     dword [ebp+NTFS.attr_size+4]
860
        pop     dword [ebp+NTFS.attr_size]
860
        pop     dword [ebp+NTFS.attr_size]
861
        pop     [ebp+NTFS.cur_buf]
861
        pop     [ebp+NTFS.cur_buf]
862
        pop     [ebp+NTFS.cur_read]
862
        pop     [ebp+NTFS.cur_read]
863
        pop     [ebp+NTFS.cur_size]
863
        pop     [ebp+NTFS.cur_size]
864
        pop     [ebp+NTFS.cur_offs]
864
        pop     [ebp+NTFS.cur_offs]
865
        jc      .errret
865
        jc      .errret
866
        lea     ecx, [ecx+ebp+NTFS.attrlist_buf+0x200-0x1A]
866
        lea     ecx, [ecx+ebp+NTFS.attrlist_buf+0x200-0x1A]
867
        cmp     [ebp+NTFS.cur_iRecord], 0
867
        cmp     [ebp+NTFS.cur_iRecord], 0
868
        jnz     .scanliststart
868
        jnz     .scanliststart
869
        add     ecx, NTFS.attrlist_mft_buf-NTFS.attrlist_buf
869
        add     ecx, NTFS.attrlist_mft_buf-NTFS.attrlist_buf
870
        jmp     .scanliststart
870
        jmp     .scanliststart
871
 
871
 
872
.doreadattr:
872
.doreadattr:
873
        mov     [ebp+NTFS.bCanContinue], 0
873
        mov     [ebp+NTFS.bCanContinue], 0
874
        cmp     byte [ecx+nonResidentFlag], 0
874
        cmp     byte [ecx+nonResidentFlag], 0
875
        jnz     .nonresident
875
        jnz     .nonresident
876
        mov     eax, [ecx+sizeWithoutHeader]
876
        mov     eax, [ecx+sizeWithoutHeader]
877
        mov     esi, eax
877
        mov     esi, eax
878
        mov     edx, [ebp+NTFS.cur_offs]
878
        mov     edx, [ebp+NTFS.cur_offs]
879
        shr     eax, 9
879
        shr     eax, 9
880
        cmp     eax, edx
880
        cmp     eax, edx
881
        jb      .okret
881
        jb      .okret
882
        shl     edx, 9
882
        shl     edx, 9
883
        sub     esi, edx
883
        sub     esi, edx
884
        movzx   eax, word [ecx+attributeOffset]
884
        movzx   eax, word [ecx+attributeOffset]
885
        add     edx, eax
885
        add     edx, eax
886
        add     edx, ecx        ; edx -> data
886
        add     edx, ecx        ; edx -> data
887
        mov     eax, [ebp+NTFS.cur_size]
887
        mov     eax, [ebp+NTFS.cur_size]
888
        cmp     eax, (0xFFFFFFFF shr 9)+1
888
        cmp     eax, (0xFFFFFFFF shr 9)+1
889
        jbe     @f
889
        jbe     @f
890
        mov     eax, (0xFFFFFFFF shr 9)+1
890
        mov     eax, (0xFFFFFFFF shr 9)+1
891
@@:
891
@@:
892
        shl     eax, 9
892
        shl     eax, 9
893
        cmp     eax, esi
893
        cmp     eax, esi
894
        jbe     @f
894
        jbe     @f
895
        mov     eax, esi
895
        mov     eax, esi
896
@@:
896
@@:
897
; eax = length, edx -> data
897
; eax = length, edx -> data
898
        mov     [ebp+NTFS.cur_read], eax
898
        mov     [ebp+NTFS.cur_read], eax
899
        mov     ecx, eax
899
        mov     ecx, eax
900
        mov     eax, edx
900
        mov     eax, edx
901
        mov     ebx, [ebp+NTFS.cur_buf]
901
        mov     ebx, [ebp+NTFS.cur_buf]
902
        call    memmove
902
        call    memmove
903
        and     [ebp+NTFS.cur_size], 0      ; CF=0
903
        and     [ebp+NTFS.cur_size], 0      ; CF=0
904
        ret
904
        ret
905
 
905
 
906
.nonresident:
906
.nonresident:
907
; Not all auxiliary records contain correct FileSize info
907
; Not all auxiliary records contain correct FileSize info
908
        mov     eax, dword [ebp+NTFS.attr_size]
908
        mov     eax, dword [ebp+NTFS.attr_size]
909
        mov     edx, dword [ebp+NTFS.attr_size+4]
909
        mov     edx, dword [ebp+NTFS.attr_size+4]
910
        cmp     edx, -1
910
        cmp     edx, -1
911
        jnz     @f
911
        jnz     @f
912
        mov     eax, [ecx+attributeRealSize]
912
        mov     eax, [ecx+attributeRealSize]
913
        mov     edx, [ecx+attributeRealSize+4]
913
        mov     edx, [ecx+attributeRealSize+4]
914
        mov     dword [ebp+NTFS.attr_size], eax
914
        mov     dword [ebp+NTFS.attr_size], eax
915
        mov     dword [ebp+NTFS.attr_size+4], edx
915
        mov     dword [ebp+NTFS.attr_size+4], edx
916
@@:
916
@@:
917
        add     eax, 0x1FF
917
        add     eax, 0x1FF
918
        adc     edx, 0
918
        adc     edx, 0
919
        shrd    eax, edx, 9
919
        shrd    eax, edx, 9
920
        sub     eax, [ebp+NTFS.cur_offs]
920
        sub     eax, [ebp+NTFS.cur_offs]
921
        ja      @f
921
        ja      @f
922
; return with nothing read
922
; return with nothing read
923
        and     [ebp+NTFS.cur_size], 0
923
        and     [ebp+NTFS.cur_size], 0
924
.okret:
924
.okret:
925
        clc
925
        clc
926
        ret
926
        ret
927
 
927
 
928
@@:
928
@@:
929
; reduce read length
929
; reduce read length
930
        and     [ebp+NTFS.cur_tail], 0
930
        and     [ebp+NTFS.cur_tail], 0
931
        cmp     [ebp+NTFS.cur_size], eax
931
        cmp     [ebp+NTFS.cur_size], eax
932
        jb      @f
932
        jb      @f
933
        mov     [ebp+NTFS.cur_size], eax
933
        mov     [ebp+NTFS.cur_size], eax
934
        mov     eax, dword [ebp+NTFS.attr_size]
934
        mov     eax, dword [ebp+NTFS.attr_size]
935
        and     eax, 0x1FF
935
        and     eax, 0x1FF
936
        mov     [ebp+NTFS.cur_tail], eax
936
        mov     [ebp+NTFS.cur_tail], eax
937
@@:
937
@@:
938
        mov     eax, [ebp+NTFS.cur_offs]
938
        mov     eax, [ebp+NTFS.cur_offs]
939
        xor     edx, edx
939
        xor     edx, edx
940
        div     [ebp+NTFS.sectors_per_cluster]
940
        div     [ebp+NTFS.sectors_per_cluster]
941
        sub     eax, [ecx+firstVCN]
941
        sub     eax, [ecx+firstVCN]
942
        jb      .okret
942
        jb      .okret
943
        mov     ebx, edx
943
        mov     ebx, edx
944
; eax = starting cluster, ebx = sector in the cluster
944
; eax = starting cluster, ebx = sector in the cluster
945
        cmp     [ebp+NTFS.cur_attr], 0x80
945
        cmp     [ebp+NTFS.cur_attr], 0x80
946
        jnz     .sys
946
        jnz     .sys
947
        cmp     [ebp+NTFS.cur_iRecord], 0
947
        cmp     [ebp+NTFS.cur_iRecord], 0
948
        jz      .sys
948
        jz      .sys
949
        push    fs_read64_app
949
        push    fs_read64_app
950
        cmp     [ebp+NTFS.bWriteAttr], 1
950
        cmp     [ebp+NTFS.bWriteAttr], 1
951
        jnz     @f
951
        jnz     @f
952
        mov     dword[esp], fs_write64_app
952
        mov     dword[esp], fs_write64_app
953
        jmp     @f
953
        jmp     @f
954
 
954
 
955
.sys:
955
.sys:
956
        push    fs_read64_sys
956
        push    fs_read64_sys
957
@@:
957
@@:
958
        sub     esp, 10h
958
        sub     esp, 10h
959
        movzx   esi, word [ecx+dataRunsOffset]
959
        movzx   esi, word [ecx+dataRunsOffset]
960
        add     esi, ecx
960
        add     esi, ecx
961
        xor     edi, edi
961
        xor     edi, edi
962
        mov     [ebp+NTFS.fragmentCount], 0
962
        mov     [ebp+NTFS.fragmentCount], 0
963
.readloop:
963
.readloop:
964
        call    ntfs_decode_mcb_entry
964
        call    ntfs_decode_mcb_entry
965
        jnc     .break
965
        jnc     .break
966
        add     edi, [esp+8]
966
        add     edi, [esp+8]
967
        sub     eax, [esp]
967
        sub     eax, [esp]
968
        jae     .readloop
968
        jae     .readloop
969
        mov     ecx, edi
969
        mov     ecx, edi
970
        add     ecx, eax
970
        add     ecx, eax
971
        add     ecx, [esp]
971
        add     ecx, [esp]
972
        neg     eax
972
        neg     eax
973
        mul     [ebp+NTFS.sectors_per_cluster]
973
        mul     [ebp+NTFS.sectors_per_cluster]
974
        xchg    eax, ecx
974
        xchg    eax, ecx
975
        mul     [ebp+NTFS.sectors_per_cluster]
975
        mul     [ebp+NTFS.sectors_per_cluster]
976
        sub     ecx, ebx
976
        sub     ecx, ebx
977
        add     eax, ebx
977
        add     eax, ebx
978
        mov     ebx, [ebp+NTFS.cur_buf]
978
        mov     ebx, [ebp+NTFS.cur_buf]
979
        cmp     ecx, [ebp+NTFS.cur_size]
979
        cmp     ecx, [ebp+NTFS.cur_size]
980
        jb      @f
980
        jb      @f
981
        mov     ecx, [ebp+NTFS.cur_size]
981
        mov     ecx, [ebp+NTFS.cur_size]
982
@@:
982
@@:
983
        mov     [ebp+NTFS.LastRead], eax
983
        mov     [ebp+NTFS.LastRead], eax
984
        push    ecx
984
        push    ecx
985
        call    dword[esp+14h]
985
        call    dword[esp+14h]
986
        pop     ecx
986
        pop     ecx
987
        test    eax, eax
987
        test    eax, eax
988
        jnz     .errread2
988
        jnz     .errread2
989
        sub     [ebp+NTFS.cur_size], ecx
989
        sub     [ebp+NTFS.cur_size], ecx
990
        add     [ebp+NTFS.cur_offs], ecx
990
        add     [ebp+NTFS.cur_offs], ecx
991
        shl     ecx, 9
991
        shl     ecx, 9
992
        add     [ebp+NTFS.cur_read], ecx
992
        add     [ebp+NTFS.cur_read], ecx
993
        add     [ebp+NTFS.cur_buf], ecx
993
        add     [ebp+NTFS.cur_buf], ecx
994
        inc     [ebp+NTFS.fragmentCount]
994
        inc     [ebp+NTFS.fragmentCount]
995
        xor     eax, eax
995
        xor     eax, eax
996
        xor     ebx, ebx
996
        xor     ebx, ebx
997
        cmp     [ebp+NTFS.cur_size], 0
997
        cmp     [ebp+NTFS.cur_size], 0
998
        jnz     .readloop
998
        jnz     .readloop
999
        add     esp, 14h
999
        add     esp, 14h
1000
        mov     eax, [ebp+NTFS.cur_tail]
1000
        mov     eax, [ebp+NTFS.cur_tail]
1001
        test    eax, eax
1001
        test    eax, eax
1002
        jz      @f
1002
        jz      @f
1003
        sub     eax, 0x200
1003
        sub     eax, 0x200
1004
        add     [ebp+NTFS.cur_read], eax
1004
        add     [ebp+NTFS.cur_read], eax
1005
@@:
1005
@@:
1006
        clc
1006
        clc
1007
        ret
1007
        ret
1008
 
1008
 
1009
.errread2:
1009
.errread2:
1010
        add     esp, 14h
1010
        add     esp, 14h
1011
        stc
1011
        stc
1012
        ret
1012
        ret
1013
 
1013
 
1014
.break:
1014
.break:
1015
        add     esp, 14h        ; CF=0
1015
        add     esp, 14h        ; CF=0
1016
        mov     [ebp+NTFS.bCanContinue], 1
1016
        mov     [ebp+NTFS.bCanContinue], 1
1017
        ret
1017
        ret
1018
 
1018
 
1019
ntfs_read_file_record:
1019
ntfs_read_file_record:
1020
; in: eax = iRecord
1020
; in: eax = iRecord
1021
; out: [ebp+NTFS.frs_buffer] -> file record
1021
; out: [ebp+NTFS.frs_buffer] -> file record
1022
; CF=1 -> failed, eax = disk error code, eax=0 -> something with FS
1022
; CF=1 -> failed, eax = disk error code, eax=0 -> something with FS
1023
    ; Read attr $DATA of $Mft, starting from eax*[ebp+NTFS.frs_size]
1023
    ; Read attr $DATA of $Mft, starting from eax*[ebp+NTFS.frs_size]
1024
        push    ecx edx
1024
        push    ecx edx
1025
        mov     ecx, [ebp+NTFS.frs_size]
1025
        mov     ecx, [ebp+NTFS.frs_size]
1026
        mul     ecx
1026
        mul     ecx
1027
        shrd    eax, edx, 9
1027
        shrd    eax, edx, 9
1028
        shr     edx, 9
1028
        shr     edx, 9
1029
        jnz     .errret
1029
        jnz     .errret
1030
        push    [ebp+NTFS.attr_iBaseRecord]
1030
        push    [ebp+NTFS.attr_iBaseRecord]
1031
        push    [ebp+NTFS.attr_offs]
1031
        push    [ebp+NTFS.attr_offs]
1032
        push    [ebp+NTFS.attr_list]
1032
        push    [ebp+NTFS.attr_list]
1033
        push    dword [ebp+NTFS.attr_size+4]
1033
        push    dword [ebp+NTFS.attr_size+4]
1034
        push    dword [ebp+NTFS.attr_size]
1034
        push    dword [ebp+NTFS.attr_size]
1035
        push    [ebp+NTFS.cur_iRecord]
1035
        push    [ebp+NTFS.cur_iRecord]
1036
        push    [ebp+NTFS.cur_attr]
1036
        push    [ebp+NTFS.cur_attr]
1037
        push    [ebp+NTFS.cur_offs]
1037
        push    [ebp+NTFS.cur_offs]
1038
        push    [ebp+NTFS.cur_size]
1038
        push    [ebp+NTFS.cur_size]
1039
        push    [ebp+NTFS.cur_buf]
1039
        push    [ebp+NTFS.cur_buf]
1040
        push    [ebp+NTFS.cur_read]
1040
        push    [ebp+NTFS.cur_read]
1041
        mov     [ebp+NTFS.cur_attr], 0x80   ; $DATA
1041
        mov     [ebp+NTFS.cur_attr], 0x80   ; $DATA
1042
        and     [ebp+NTFS.cur_iRecord], 0   ; $Mft
1042
        and     [ebp+NTFS.cur_iRecord], 0   ; $Mft
1043
        mov     [ebp+NTFS.cur_offs], eax
1043
        mov     [ebp+NTFS.cur_offs], eax
1044
        shr     ecx, 9
1044
        shr     ecx, 9
1045
        mov     [ebp+NTFS.cur_size], ecx
1045
        mov     [ebp+NTFS.cur_size], ecx
1046
        mov     eax, [ebp+NTFS.frs_buffer]
1046
        mov     eax, [ebp+NTFS.frs_buffer]
1047
        mov     [ebp+NTFS.cur_buf], eax
1047
        mov     [ebp+NTFS.cur_buf], eax
1048
        call    ntfs_read_attr
1048
        call    ntfs_read_attr
1049
        mov     edx, [ebp+NTFS.cur_read]
1049
        mov     edx, [ebp+NTFS.cur_read]
1050
        pop     [ebp+NTFS.cur_read]
1050
        pop     [ebp+NTFS.cur_read]
1051
        pop     [ebp+NTFS.cur_buf]
1051
        pop     [ebp+NTFS.cur_buf]
1052
        pop     [ebp+NTFS.cur_size]
1052
        pop     [ebp+NTFS.cur_size]
1053
        pop     [ebp+NTFS.cur_offs]
1053
        pop     [ebp+NTFS.cur_offs]
1054
        pop     [ebp+NTFS.cur_attr]
1054
        pop     [ebp+NTFS.cur_attr]
1055
        pop     [ebp+NTFS.cur_iRecord]
1055
        pop     [ebp+NTFS.cur_iRecord]
1056
        pop     dword [ebp+NTFS.attr_size]
1056
        pop     dword [ebp+NTFS.attr_size]
1057
        pop     dword [ebp+NTFS.attr_size+4]
1057
        pop     dword [ebp+NTFS.attr_size+4]
1058
        pop     [ebp+NTFS.attr_list]
1058
        pop     [ebp+NTFS.attr_list]
1059
        pop     [ebp+NTFS.attr_offs]
1059
        pop     [ebp+NTFS.attr_offs]
1060
        pop     [ebp+NTFS.attr_iBaseRecord]
1060
        pop     [ebp+NTFS.attr_iBaseRecord]
1061
        jc      .ret
1061
        jc      .ret
1062
        cmp     edx, [ebp+NTFS.frs_size]
1062
        cmp     edx, [ebp+NTFS.frs_size]
1063
        jnz     .errret
1063
        jnz     .errret
1064
        mov     eax, [ebp+NTFS.LastRead]
1064
        mov     eax, [ebp+NTFS.LastRead]
1065
        mov     [ebp+NTFS.mftLastRead], eax
1065
        mov     [ebp+NTFS.mftLastRead], eax
1066
        mov     eax, [ebp+NTFS.frs_buffer]
1066
        mov     eax, [ebp+NTFS.frs_buffer]
1067
        cmp     dword [eax], 'FILE'
1067
        cmp     dword [eax], 'FILE'
1068
        jnz     .errret
1068
        jnz     .errret
1069
        push    ebx
1069
        push    ebx
1070
        mov     ebx, eax
1070
        mov     ebx, eax
1071
        call    ntfs_restore_usa_frs
1071
        call    ntfs_restore_usa_frs
1072
        pop     ebx
1072
        pop     ebx
1073
        jc      .errret
1073
        jc      .errret
1074
.ret:
1074
.ret:
1075
        pop     edx ecx
1075
        pop     edx ecx
1076
        ret
1076
        ret
1077
 
1077
 
1078
.errret:
1078
.errret:
1079
        pop     edx ecx
1079
        pop     edx ecx
1080
        xor     eax, eax
1080
        xor     eax, eax
1081
        stc
1081
        stc
1082
        ret
1082
        ret
1083
 
1083
 
1084
ntfs_restore_usa_frs:
1084
ntfs_restore_usa_frs:
1085
        mov     eax, [ebp+NTFS.frs_size]
1085
        mov     eax, [ebp+NTFS.frs_size]
1086
ntfs_restore_usa:
1086
ntfs_restore_usa:
1087
;   in:
1087
;   in:
1088
; ebx -> record
1088
; ebx -> record
1089
; eax = size in bytes
1089
; eax = size in bytes
1090
        pushad
1090
        pushad
1091
        shr     eax, 9
1091
        shr     eax, 9
1092
        mov     ecx, eax
1092
        mov     ecx, eax
1093
        inc     eax
1093
        inc     eax
1094
        cmp     [ebx+updateSequenceSize], ax
1094
        cmp     [ebx+updateSequenceSize], ax
1095
        jnz     .err
1095
        jnz     .err
1096
        movzx   eax, word [ebx+updateSequenceOffset]
1096
        movzx   eax, word [ebx+updateSequenceOffset]
1097
        lea     esi, [eax+ebx]
1097
        lea     esi, [eax+ebx]
1098
        lodsw
1098
        lodsw
1099
        mov     edx, eax
1099
        mov     edx, eax
1100
        lea     edi, [ebx+0x1FE]
1100
        lea     edi, [ebx+0x1FE]
1101
@@:
1101
@@:
1102
        cmp     [edi], dx
1102
        cmp     [edi], dx
1103
        jnz     .err
1103
        jnz     .err
1104
        lodsw
1104
        lodsw
1105
        stosw
1105
        stosw
1106
        add     edi, 0x1FE
1106
        add     edi, 0x1FE
1107
        loop    @b
1107
        loop    @b
1108
        popad
1108
        popad
1109
        clc
1109
        clc
1110
        ret
1110
        ret
1111
 
1111
 
1112
.err:
1112
.err:
1113
        popad
1113
        popad
1114
        stc
1114
        stc
1115
        ret
1115
        ret
1116
 
1116
 
1117
ntfs_decode_mcb_entry:
1117
ntfs_decode_mcb_entry:
1118
;   in:
1118
;   in:
1119
; esi -> MCB entry
1119
; esi -> MCB entry
1120
; esp -> buffer (16 bytes)
1120
; esp -> buffer (16 bytes)
1121
;   out:
1121
;   out:
1122
; esi -> next MCB entry
1122
; esi -> next MCB entry
1123
; esp -> data run size
1123
; esp -> data run size
1124
; esp+8 -> cluster (delta)
1124
; esp+8 -> cluster (delta)
1125
; CF=0 -> MCB end
1125
; CF=0 -> MCB end
1126
        push    eax ecx edi
1126
        push    eax ecx edi
1127
        lea     edi, [esp+16]
1127
        lea     edi, [esp+16]
1128
        xor     eax, eax
1128
        xor     eax, eax
1129
        lodsb
1129
        lodsb
1130
        test    al, al
1130
        test    al, al
1131
        jz      .end
1131
        jz      .end
1132
        mov     ecx, eax
1132
        mov     ecx, eax
1133
        and     ecx, 0xF
1133
        and     ecx, 0xF
1134
        cmp     ecx, 8
1134
        cmp     ecx, 8
1135
        ja      .end
1135
        ja      .end
1136
        push    ecx
1136
        push    ecx
1137
        rep movsb
1137
        rep movsb
1138
        pop     ecx
1138
        pop     ecx
1139
        sub     ecx, 8
1139
        sub     ecx, 8
1140
        neg     ecx
1140
        neg     ecx
1141
        cmp     byte [esi-1], 80h
1141
        cmp     byte [esi-1], 80h
1142
        jae     .end
1142
        jae     .end
1143
        push    eax
1143
        push    eax
1144
        xor     eax, eax
1144
        xor     eax, eax
1145
        rep stosb
1145
        rep stosb
1146
        pop     ecx
1146
        pop     ecx
1147
        shr     ecx, 4
1147
        shr     ecx, 4
1148
        cmp     ecx, 8
1148
        cmp     ecx, 8
1149
        ja      .end
1149
        ja      .end
1150
        push    ecx
1150
        push    ecx
1151
        rep movsb
1151
        rep movsb
1152
        pop     ecx
1152
        pop     ecx
1153
        sub     ecx, 8
1153
        sub     ecx, 8
1154
        neg     ecx
1154
        neg     ecx
1155
        cmp     byte [esi-1], 80h
1155
        cmp     byte [esi-1], 80h
1156
        cmc
1156
        cmc
1157
        sbb     eax, eax
1157
        sbb     eax, eax
1158
        rep stosb
1158
        rep stosb
1159
        stc
1159
        stc
1160
.end:
1160
.end:
1161
        pop     edi ecx eax
1161
        pop     edi ecx eax
1162
        ret
1162
        ret
1163
 
1163
 
1164
ntfs_find_lfn:
1164
ntfs_find_lfn:
1165
; in: esi -> path string in UTF-8
1165
; in: esi -> path string in UTF-8
1166
;   out:
1166
;   out:
1167
; [ebp+NTFS.cur_iRecord] = target fileRecord
1167
; [ebp+NTFS.cur_iRecord] = target fileRecord
1168
; eax -> target index in the node
1168
; eax -> target index in the node
1169
; [ebp+NTFS.LastRead] = target node location
1169
; [ebp+NTFS.LastRead] = target node location
1170
; [ebp+NTFS.indexPointer] -> index, that points the target subnode
1170
; [ebp+NTFS.indexPointer] -> index, that points the target subnode
1171
; [ebp+NTFS.nodeLastRead] = branch node location
1171
; [ebp+NTFS.nodeLastRead] = branch node location
1172
; [ebp+NTFS.indexRoot] -> attribute
1172
; [ebp+NTFS.indexRoot] -> attribute
1173
; [ebp+NTFS.rootLastRead] = directory fileRecord location
1173
; [ebp+NTFS.rootLastRead] = directory fileRecord location
1174
; [ebp+NTFS.cur_size] = index record size in sectors
1174
; [ebp+NTFS.cur_size] = index record size in sectors
1175
; [ebp+NTFS.cur_subnode_size] = index record size in clusters or sectors
1175
; [ebp+NTFS.cur_subnode_size] = index record size in clusters or sectors
1176
; CF=1 -> file not found, eax=0 -> error
1176
; CF=1 -> file not found, eax=0 -> error
1177
        mov     [ebp+NTFS.cur_iRecord], 5   ; start from root directory
1177
        mov     [ebp+NTFS.cur_iRecord], 5   ; start from root directory
1178
.doit2:
1178
.doit2:
1179
        mov     [ebp+NTFS.cur_attr], 0x90   ; $INDEX_ROOT
1179
        mov     [ebp+NTFS.cur_attr], 0x90   ; $INDEX_ROOT
1180
        and     [ebp+NTFS.cur_offs], 0
1180
        and     [ebp+NTFS.cur_offs], 0
1181
        mov     eax, [ebp+NTFS.cur_index_size]
1181
        mov     eax, [ebp+NTFS.cur_index_size]
1182
        mov     [ebp+NTFS.cur_size], eax
1182
        mov     [ebp+NTFS.cur_size], eax
1183
        mov     eax, [ebp+NTFS.cur_index_buf]
1183
        mov     eax, [ebp+NTFS.cur_index_buf]
1184
        mov     [ebp+NTFS.cur_buf], eax
1184
        mov     [ebp+NTFS.cur_buf], eax
1185
        call    ntfs_read_attr
1185
        call    ntfs_read_attr
1186
        mov     eax, 0
1186
        mov     eax, 0
1187
        jc      .ret
1187
        jc      .ret
1188
        cmp     [ebp+NTFS.cur_read], 0x20
1188
        cmp     [ebp+NTFS.cur_read], 0x20
1189
        jc      .ret
1189
        jc      .ret
1190
        push    esi
1190
        push    esi
1191
        pushad
1191
        pushad
1192
        mov     esi, [ebp+NTFS.cur_index_buf]
1192
        mov     esi, [ebp+NTFS.cur_index_buf]
1193
        mov     eax, [esi+indexRecordSize]
1193
        mov     eax, [esi+indexRecordSize]
1194
        shr     eax, 9
1194
        shr     eax, 9
1195
        cmp     [ebp+NTFS.cur_index_size], eax
1195
        cmp     [ebp+NTFS.cur_index_size], eax
1196
        jc      .realloc
1196
        jc      .realloc
1197
        mov     [ebp+NTFS.cur_size], eax
1197
        mov     [ebp+NTFS.cur_size], eax
1198
        mov     al, [esi+indexRecordSizeClus]
1198
        mov     al, [esi+indexRecordSizeClus]
1199
        mov     [ebp+NTFS.cur_subnode_size], eax
1199
        mov     [ebp+NTFS.cur_subnode_size], eax
1200
        add     esi, rootNode
1200
        add     esi, rootNode
1201
        mov     eax, [esi+nodeRealSize]
1201
        mov     eax, [esi+nodeRealSize]
1202
        add     eax, rootNode
1202
        add     eax, rootNode
1203
        cmp     [ebp+NTFS.cur_read], eax
1203
        cmp     [ebp+NTFS.cur_read], eax
1204
        jc      .err
1204
        jc      .err
1205
        mov     eax, [ebp+NTFS.mftLastRead]
1205
        mov     eax, [ebp+NTFS.mftLastRead]
1206
        mov     [ebp+NTFS.rootLastRead], eax
1206
        mov     [ebp+NTFS.rootLastRead], eax
1207
        mov     eax, [ebp+NTFS.attr_offs]
1207
        mov     eax, [ebp+NTFS.attr_offs]
1208
        mov     [ebp+NTFS.indexRoot], eax
1208
        mov     [ebp+NTFS.indexRoot], eax
1209
.scanloop:  ; esi -> current index node
1209
.scanloop:  ; esi -> current index node
1210
        add     esi, [esi+indexOffset]
1210
        add     esi, [esi+indexOffset]
1211
.scanloopint:
1211
.scanloopint:
1212
        push    esi
1212
        push    esi
1213
        test    byte [esi+indexFlags], 2
1213
        test    byte [esi+indexFlags], 2
1214
        jnz     .subnode
1214
        jnz     .subnode
1215
        movzx   ecx, byte [esi+fileNameLength]
1215
        movzx   ecx, byte [esi+fileNameLength]
1216
        lea     edi, [esi+fileName]
1216
        lea     edi, [esi+fileName]
1217
        mov     esi, [esp+8]
1217
        mov     esi, [esp+8]
1218
@@:
1218
@@:
1219
        call    utf8to16
1219
        call    utf8to16
1220
        cmp     ax, '/'
1220
        cmp     ax, '/'
1221
        jz      .subnode
1221
        jz      .subnode
1222
        call    utf16toUpper
1222
        call    utf16toUpper
1223
        push    eax
1223
        push    eax
1224
        mov     ax, [edi]
1224
        mov     ax, [edi]
1225
        call    utf16toUpper
1225
        call    utf16toUpper
1226
        cmp     [esp], ax
1226
        cmp     [esp], ax
1227
        pop     eax
1227
        pop     eax
1228
        jc      .subnode
1228
        jc      .subnode
1229
        jnz     .scanloopcont
1229
        jnz     .scanloopcont
1230
        add     edi, 2
1230
        add     edi, 2
1231
        loop    @b
1231
        loop    @b
1232
        call    utf8to16
1232
        call    utf8to16
1233
        cmp     ax, '/'
1233
        cmp     ax, '/'
1234
        jz      .found
1234
        jz      .found
1235
        test    ax, ax
1235
        test    ax, ax
1236
        jz      .found
1236
        jz      .found
1237
.scanloopcont:
1237
.scanloopcont:
1238
        pop     esi
1238
        pop     esi
1239
        movzx   eax, word [esi+indexAllocatedSize]
1239
        movzx   eax, word [esi+indexAllocatedSize]
1240
        add     esi, eax
1240
        add     esi, eax
1241
        jmp     .scanloopint
1241
        jmp     .scanloopint
1242
 
1242
 
1243
.realloc:
1243
.realloc:
1244
        mov     edi, eax
1244
        mov     edi, eax
1245
        mov     eax, [esi+indexRecordSize]
1245
        mov     eax, [esi+indexRecordSize]
1246
        shl     eax, 1
1246
        shl     eax, 1
1247
        stdcall kernel_alloc, eax
1247
        stdcall kernel_alloc, eax
1248
        test    eax, eax
1248
        test    eax, eax
1249
        jz      .err
1249
        jz      .err
1250
        mov     edx, [ebp+NTFS.cur_index_buf]
1250
        mov     edx, [ebp+NTFS.cur_index_buf]
1251
        cmp     edx, [ebp+NTFS.secondIndexBuffer]
1251
        cmp     edx, [ebp+NTFS.secondIndexBuffer]
1252
        jc      @f
1252
        jc      @f
1253
        mov     edx, [ebp+NTFS.secondIndexBuffer]
1253
        mov     edx, [ebp+NTFS.secondIndexBuffer]
1254
@@:
1254
@@:
1255
        mov     [ebp+NTFS.cur_index_buf], eax
1255
        mov     [ebp+NTFS.cur_index_buf], eax
1256
        add     eax, [esi+indexRecordSize]
1256
        add     eax, [esi+indexRecordSize]
1257
        mov     [ebp+NTFS.secondIndexBuffer], eax
1257
        mov     [ebp+NTFS.secondIndexBuffer], eax
1258
        mov     [ebp+NTFS.cur_index_size], edi
1258
        mov     [ebp+NTFS.cur_index_size], edi
1259
        stdcall kernel_free, edx
1259
        stdcall kernel_free, edx
1260
        popad
1260
        popad
1261
        pop     eax
1261
        pop     eax
1262
        jmp     .doit2
1262
        jmp     .doit2
1263
 
1263
 
1264
.notfound:
1264
.notfound:
1265
        mov     [esp+28], esi
1265
        mov     [esp+28], esi
1266
.err:
1266
.err:
1267
        popad
1267
        popad
1268
        stc
1268
        stc
1269
.ret2:
1269
.ret2:
1270
        pop     esi
1270
        pop     esi
1271
.ret:
1271
.ret:
1272
        ret
1272
        ret
1273
 
1273
 
1274
.subnode:
1274
.subnode:
1275
        pop     esi
1275
        pop     esi
1276
        test    byte [esi+indexFlags], 1
1276
        test    byte [esi+indexFlags], 1
1277
        jz      .notfound
1277
        jz      .notfound
1278
        mov     eax, [ebp+NTFS.LastRead]
1278
        mov     eax, [ebp+NTFS.LastRead]
1279
        mov     [ebp+NTFS.nodeLastRead], eax
1279
        mov     [ebp+NTFS.nodeLastRead], eax
1280
        mov     [ebp+NTFS.indexPointer], esi
1280
        mov     [ebp+NTFS.indexPointer], esi
1281
        movzx   eax, word [esi+indexAllocatedSize]
1281
        movzx   eax, word [esi+indexAllocatedSize]
1282
        mov     eax, [esi+eax-8]
1282
        mov     eax, [esi+eax-8]
1283
        mov     edx, [ebp+NTFS.cur_size]
1283
        mov     edx, [ebp+NTFS.cur_size]
1284
        push    edx
1284
        push    edx
1285
        cmp     edx, [ebp+NTFS.cur_subnode_size]
1285
        cmp     edx, [ebp+NTFS.cur_subnode_size]
1286
        jz      @f
1286
        jz      @f
1287
        mul     [ebp+NTFS.sectors_per_cluster]
1287
        mul     [ebp+NTFS.sectors_per_cluster]
1288
@@:
1288
@@:
1289
        mov     esi, [ebp+NTFS.cur_index_buf]
1289
        mov     esi, [ebp+NTFS.cur_index_buf]
1290
        xchg    [ebp+NTFS.secondIndexBuffer], esi
1290
        xchg    [ebp+NTFS.secondIndexBuffer], esi
1291
        mov     [ebp+NTFS.cur_index_buf], esi
1291
        mov     [ebp+NTFS.cur_index_buf], esi
1292
        mov     [ebp+NTFS.cur_buf], esi
1292
        mov     [ebp+NTFS.cur_buf], esi
1293
        mov     [ebp+NTFS.cur_attr], 0xA0   ; $INDEX_ALLOCATION
1293
        mov     [ebp+NTFS.cur_attr], 0xA0   ; $INDEX_ALLOCATION
1294
        mov     [ebp+NTFS.cur_offs], eax
1294
        mov     [ebp+NTFS.cur_offs], eax
1295
        call    ntfs_read_attr.newAttribute
1295
        call    ntfs_read_attr.newAttribute
1296
        pop     eax
1296
        pop     eax
1297
        mov     [ebp+NTFS.cur_size], eax
1297
        mov     [ebp+NTFS.cur_size], eax
1298
        shl     eax, 9
1298
        shl     eax, 9
1299
        cmp     [ebp+NTFS.cur_read], eax
1299
        cmp     [ebp+NTFS.cur_read], eax
1300
        jnz     .err
1300
        jnz     .err
1301
        cmp     dword [esi], 'INDX'
1301
        cmp     dword [esi], 'INDX'
1302
        jnz     .err
1302
        jnz     .err
1303
        mov     ebx, esi
1303
        mov     ebx, esi
1304
        call    ntfs_restore_usa
1304
        call    ntfs_restore_usa
1305
        jc      .err
1305
        jc      .err
1306
        add     esi, recordNode
1306
        add     esi, recordNode
1307
        jmp     .scanloop
1307
        jmp     .scanloop
1308
 
1308
 
1309
.found:
1309
.found:
1310
        mov     [esp+8], esi
1310
        mov     [esp+8], esi
1311
        pop     eax
1311
        pop     eax
1312
        mov     [esp+28], eax
1312
        mov     [esp+28], eax
1313
        mov     eax, [eax+fileRecordReference]
1313
        mov     eax, [eax+fileRecordReference]
1314
        mov     [ebp+NTFS.cur_iRecord], eax
1314
        mov     [ebp+NTFS.cur_iRecord], eax
1315
        popad
1315
        popad
1316
        cmp     byte [esi-1], 0
1316
        cmp     byte [esi-1], 0
1317
        jz      .ret2
1317
        jz      .ret2
1318
        pop     eax
1318
        pop     eax
1319
        jmp     .doit2
1319
        jmp     .doit2
1320
 
1320
 
1321
;----------------------------------------------------------------
1321
;----------------------------------------------------------------
1322
ntfs_ReadFile:
1322
ntfs_ReadFile:
1323
        call    ntfs_lock
1323
        call    ntfs_lock
1324
        call    ntfs_find_lfn
1324
        call    ntfs_find_lfn
1325
        jc      ntfsNotFound
1325
        jc      ntfsNotFound
1326
        mov     [ebp+NTFS.cur_attr], 0x80   ; $DATA
1326
        mov     [ebp+NTFS.cur_attr], 0x80   ; $DATA
1327
        and     [ebp+NTFS.cur_offs], 0
1327
        and     [ebp+NTFS.cur_offs], 0
1328
        and     [ebp+NTFS.cur_size], 0
1328
        and     [ebp+NTFS.cur_size], 0
1329
        call    ntfs_read_attr
1329
        call    ntfs_read_attr
1330
        jc      ntfsDenied
1330
        jc      ntfsDenied
1331
        xor     eax, eax
1331
        xor     eax, eax
1332
        push    eax
1332
        push    eax
1333
        cmp     dword [ebx+8], 0x200
1333
        cmp     dword [ebx+8], 0x200
1334
        jnc     .eof
1334
        jnc     .eof
1335
        mov     ecx, [ebx+12]
1335
        mov     ecx, [ebx+12]
1336
        mov     edx, [ebx+16]
1336
        mov     edx, [ebx+16]
1337
        mov     eax, [ebx+4]
1337
        mov     eax, [ebx+4]
1338
        test    eax, 0x1FF
1338
        test    eax, 0x1FF
1339
        jz      .alignedstart
1339
        jz      .alignedstart
1340
        push    edx
1340
        push    edx
1341
        mov     edx, [ebx+8]
1341
        mov     edx, [ebx+8]
1342
        shrd    eax, edx, 9
1342
        shrd    eax, edx, 9
1343
        pop     edx
1343
        pop     edx
1344
        mov     [ebp+NTFS.cur_offs], eax
1344
        mov     [ebp+NTFS.cur_offs], eax
1345
        mov     [ebp+NTFS.cur_size], 1
1345
        mov     [ebp+NTFS.cur_size], 1
1346
        lea     eax, [ebp+NTFS.bitmap_buf]
1346
        lea     eax, [ebp+NTFS.bitmap_buf]
1347
        mov     [ebp+NTFS.cur_buf], eax
1347
        mov     [ebp+NTFS.cur_buf], eax
1348
        call    ntfs_read_attr.continue
1348
        call    ntfs_read_attr.continue
1349
        mov     eax, [ebx+4]
1349
        mov     eax, [ebx+4]
1350
        and     eax, 0x1FF
1350
        and     eax, 0x1FF
1351
        lea     esi, [ebp+NTFS.bitmap_buf+eax]
1351
        lea     esi, [ebp+NTFS.bitmap_buf+eax]
1352
        sub     eax, [ebp+NTFS.cur_read]
1352
        sub     eax, [ebp+NTFS.cur_read]
1353
        jae     .eof
1353
        jae     .eof
1354
        neg     eax
1354
        neg     eax
1355
        push    ecx
1355
        push    ecx
1356
        cmp     ecx, eax
1356
        cmp     ecx, eax
1357
        jb      @f
1357
        jb      @f
1358
        mov     ecx, eax
1358
        mov     ecx, eax
1359
@@:
1359
@@:
1360
        mov     [esp+4], ecx
1360
        mov     [esp+4], ecx
1361
        mov     edi, edx
1361
        mov     edi, edx
1362
        rep movsb
1362
        rep movsb
1363
        mov     edx, edi
1363
        mov     edx, edi
1364
        pop     ecx
1364
        pop     ecx
1365
        sub     ecx, [esp]
1365
        sub     ecx, [esp]
1366
        jz      .retok
1366
        jz      .retok
1367
        cmp     [ebp+NTFS.cur_read], 0x200
1367
        cmp     [ebp+NTFS.cur_read], 0x200
1368
        jnz     .eof
1368
        jnz     .eof
1369
.alignedstart:
1369
.alignedstart:
1370
        mov     eax, [ebx+4]
1370
        mov     eax, [ebx+4]
1371
        push    edx
1371
        push    edx
1372
        mov     edx, [ebx+8]
1372
        mov     edx, [ebx+8]
1373
        add     eax, 511
1373
        add     eax, 511
1374
        adc     edx, 0
1374
        adc     edx, 0
1375
        shrd    eax, edx, 9
1375
        shrd    eax, edx, 9
1376
        pop     edx
1376
        pop     edx
1377
        mov     [ebp+NTFS.cur_offs], eax
1377
        mov     [ebp+NTFS.cur_offs], eax
1378
        mov     [ebp+NTFS.cur_buf], edx
1378
        mov     [ebp+NTFS.cur_buf], edx
1379
        mov     eax, ecx
1379
        mov     eax, ecx
1380
        shr     eax, 9
1380
        shr     eax, 9
1381
        mov     [ebp+NTFS.cur_size], eax
1381
        mov     [ebp+NTFS.cur_size], eax
1382
        add     eax, [ebp+NTFS.cur_offs]
1382
        add     eax, [ebp+NTFS.cur_offs]
1383
        push    eax
1383
        push    eax
1384
        call    ntfs_read_attr.continue
1384
        call    ntfs_read_attr.continue
1385
        pop     [ebp+NTFS.cur_offs]
1385
        pop     [ebp+NTFS.cur_offs]
1386
        mov     eax, [ebp+NTFS.cur_read]
1386
        mov     eax, [ebp+NTFS.cur_read]
1387
        add     [esp], eax
1387
        add     [esp], eax
1388
        mov     eax, ecx
1388
        mov     eax, ecx
1389
        and     eax, not 0x1FF
1389
        and     eax, not 0x1FF
1390
        cmp     [ebp+NTFS.cur_read], eax
1390
        cmp     [ebp+NTFS.cur_read], eax
1391
        jnz     .eof
1391
        jnz     .eof
1392
        and     ecx, 0x1FF
1392
        and     ecx, 0x1FF
1393
        jz      .retok
1393
        jz      .retok
1394
        add     edx, [ebp+NTFS.cur_read]
1394
        add     edx, [ebp+NTFS.cur_read]
1395
        mov     [ebp+NTFS.cur_size], 1
1395
        mov     [ebp+NTFS.cur_size], 1
1396
        lea     eax, [ebp+NTFS.bitmap_buf]
1396
        lea     eax, [ebp+NTFS.bitmap_buf]
1397
        mov     [ebp+NTFS.cur_buf], eax
1397
        mov     [ebp+NTFS.cur_buf], eax
1398
        call    ntfs_read_attr.continue
1398
        call    ntfs_read_attr.continue
1399
        cmp     [ebp+NTFS.cur_read], ecx
1399
        cmp     [ebp+NTFS.cur_read], ecx
1400
        jb      @f
1400
        jb      @f
1401
        mov     [ebp+NTFS.cur_read], ecx
1401
        mov     [ebp+NTFS.cur_read], ecx
1402
@@:
1402
@@:
1403
        xchg    ecx, [ebp+NTFS.cur_read]
1403
        xchg    ecx, [ebp+NTFS.cur_read]
1404
        push    ecx
1404
        push    ecx
1405
        mov     edi, edx
1405
        mov     edi, edx
1406
        lea     esi, [ebp+NTFS.bitmap_buf]
1406
        lea     esi, [ebp+NTFS.bitmap_buf]
1407
        add     [esp+4], ecx
1407
        add     [esp+4], ecx
1408
        rep movsb
1408
        rep movsb
1409
        pop     ecx
1409
        pop     ecx
1410
        cmp     ecx, [ebp+NTFS.cur_read]
1410
        cmp     ecx, [ebp+NTFS.cur_read]
1411
        jnz     .eof
1411
        jnz     .eof
1412
.retok:
1412
.retok:
1413
        pushd   0
1413
        pushd   0
1414
.ret:
1414
.ret:
1415
        call    ntfs_unlock
1415
        call    ntfs_unlock
1416
        pop     eax ebx
1416
        pop     eax ebx
1417
        ret
1417
        ret
1418
 
1418
 
1419
.eof:
1419
.eof:
1420
        push    ERROR_END_OF_FILE
1420
        push    ERROR_END_OF_FILE
1421
        jmp     .ret
1421
        jmp     .ret
1422
 
1422
 
1423
;----------------------------------------------------------------
1423
;----------------------------------------------------------------
1424
ntfs_ReadFolder:
1424
ntfs_ReadFolder:
1425
        call    ntfs_lock
1425
        call    ntfs_lock
1426
        mov     [ebp+NTFS.cur_iRecord], 5   ; root directory
1426
        mov     [ebp+NTFS.cur_iRecord], 5   ; root directory
1427
        cmp     byte [esi], 0
1427
        cmp     byte [esi], 0
1428
        jz      @f
1428
        jz      @f
1429
        call    ntfs_find_lfn
1429
        call    ntfs_find_lfn
1430
        jc      ntfsNotFound
1430
        jc      ntfsNotFound
1431
@@:
1431
@@:
1432
        mov     [ebp+NTFS.cur_attr], 0x10   ; $STANDARD_INFORMATION
1432
        mov     [ebp+NTFS.cur_attr], 0x10   ; $STANDARD_INFORMATION
1433
        and     [ebp+NTFS.cur_offs], 0
1433
        and     [ebp+NTFS.cur_offs], 0
1434
        mov     [ebp+NTFS.cur_size], 1
1434
        mov     [ebp+NTFS.cur_size], 1
1435
        lea     eax, [ebp+NTFS.bitmap_buf]
1435
        lea     eax, [ebp+NTFS.bitmap_buf]
1436
        mov     [ebp+NTFS.cur_buf], eax
1436
        mov     [ebp+NTFS.cur_buf], eax
1437
        call    ntfs_read_attr
1437
        call    ntfs_read_attr
1438
        jc      ntfsFail
1438
        jc      ntfsFail
1439
        mov     [ebp+NTFS.cur_attr], 0x90   ; $INDEX_ROOT
1439
        mov     [ebp+NTFS.cur_attr], 0x90   ; $INDEX_ROOT
1440
.doit:
1440
.doit:
1441
        mov     eax, [ebp+NTFS.cur_index_size]
1441
        mov     eax, [ebp+NTFS.cur_index_size]
1442
        mov     [ebp+NTFS.cur_size], eax
1442
        mov     [ebp+NTFS.cur_size], eax
1443
        mov     eax, [ebp+NTFS.cur_index_buf]
1443
        mov     eax, [ebp+NTFS.cur_index_buf]
1444
        mov     [ebp+NTFS.cur_buf], eax
1444
        mov     [ebp+NTFS.cur_buf], eax
1445
        call    ntfs_read_attr.newAttribute
1445
        call    ntfs_read_attr.newAttribute
1446
        jc      ntfsFail
1446
        jc      ntfsFail
1447
        cmp     [ebp+NTFS.cur_read], 0x20
1447
        cmp     [ebp+NTFS.cur_read], 0x20
1448
        jc      ntfsFail
1448
        jc      ntfsFail
1449
        mov     esi, [ebp+NTFS.cur_index_buf]
1449
        mov     esi, [ebp+NTFS.cur_index_buf]
1450
        mov     eax, [esi+indexRecordSize]
1450
        mov     eax, [esi+indexRecordSize]
1451
        shr     eax, 9
1451
        shr     eax, 9
1452
        cmp     [ebp+NTFS.cur_index_size], eax
1452
        cmp     [ebp+NTFS.cur_index_size], eax
1453
        jc      .realloc
1453
        jc      .realloc
1454
        mov     [ebp+NTFS.cur_subnode_size], eax
1454
        mov     [ebp+NTFS.cur_subnode_size], eax
1455
        add     esi, rootNode
1455
        add     esi, rootNode
1456
        mov     eax, [esi+nodeRealSize]
1456
        mov     eax, [esi+nodeRealSize]
1457
        add     eax, rootNode
1457
        add     eax, rootNode
1458
        cmp     [ebp+NTFS.cur_read], eax
1458
        cmp     [ebp+NTFS.cur_read], eax
1459
        jc      ntfsFail
1459
        jc      ntfsFail
1460
        mov     edi, [ebx+16]
1460
        mov     edi, [ebx+16]
1461
        mov     ecx, [ebx+12]
1461
        mov     ecx, [ebx+12]
1462
        pushd   [ebx]
1462
        pushd   [ebx]
1463
        pushd   [ebx+8]     ; read ANSI/UNICODE name
1463
        pushd   [ebx+8]     ; read ANSI/UNICODE name
1464
        push    edi
1464
        push    edi
1465
        mov     edx, esp
1465
        mov     edx, esp
1466
        mov     ebx, [ebx+4]
1466
        mov     ebx, [ebx+4]
1467
; init header
1467
; init header
1468
        xor     eax, eax
1468
        xor     eax, eax
1469
        mov     [edi+8], eax
1469
        mov     [edi+8], eax
1470
        mov     [edi+4], eax
1470
        mov     [edi+4], eax
1471
        inc     eax
1471
        inc     eax
1472
        mov     [edi], eax      ; version
1472
        mov     [edi], eax      ; version
1473
        add     edi, 32
1473
        add     edi, 32
1474
; edi -> BDFE, esi -> current index data, ebx = first wanted block,
1474
; edi -> BDFE, esi -> current index data, ebx = first wanted block,
1475
; ecx = number of blocks to read
1475
; ecx = number of blocks to read
1476
; edx -> parameters block: dd , dd 
1476
; edx -> parameters block: dd , dd 
1477
        cmp     [ebp+NTFS.cur_iRecord], 5
1477
        cmp     [ebp+NTFS.cur_iRecord], 5
1478
        jz      .skip_specials
1478
        jz      .skip_specials
1479
; dot and dotdot entries
1479
; dot and dotdot entries
1480
        push    esi
1480
        push    esi
1481
        xor     esi, esi
1481
        xor     esi, esi
1482
        call    .add_special_entry
1482
        call    .add_special_entry
1483
        inc     esi
1483
        inc     esi
1484
        call    .add_special_entry
1484
        call    .add_special_entry
1485
        pop     esi
1485
        pop     esi
1486
.skip_specials:
1486
.skip_specials:
1487
; at first, dump index root
1487
; at first, dump index root
1488
        add     esi, [esi+indexOffset]
1488
        add     esi, [esi+indexOffset]
1489
.dump_root:
1489
.dump_root:
1490
        test    byte [esi+indexFlags], 2
1490
        test    byte [esi+indexFlags], 2
1491
        jnz     .dump_root_done
1491
        jnz     .dump_root_done
1492
        call    .add_entry
1492
        call    .add_entry
1493
        movzx   eax, word [esi+indexAllocatedSize]
1493
        movzx   eax, word [esi+indexAllocatedSize]
1494
        add     esi, eax
1494
        add     esi, eax
1495
        jmp     .dump_root
1495
        jmp     .dump_root
1496
 
1496
 
1497
.realloc:
1497
.realloc:
1498
        mov     edi, eax
1498
        mov     edi, eax
1499
        mov     eax, [esi+indexRecordSize]
1499
        mov     eax, [esi+indexRecordSize]
1500
        shl     eax, 1
1500
        shl     eax, 1
1501
        stdcall kernel_alloc, eax
1501
        stdcall kernel_alloc, eax
1502
        test    eax, eax
1502
        test    eax, eax
1503
        jz      ntfsFail
1503
        jz      ntfsFail
1504
        mov     edx, [ebp+NTFS.cur_index_buf]
1504
        mov     edx, [ebp+NTFS.cur_index_buf]
1505
        cmp     edx, [ebp+NTFS.secondIndexBuffer]
1505
        cmp     edx, [ebp+NTFS.secondIndexBuffer]
1506
        jc      @f
1506
        jc      @f
1507
        mov     edx, [ebp+NTFS.secondIndexBuffer]
1507
        mov     edx, [ebp+NTFS.secondIndexBuffer]
1508
@@:
1508
@@:
1509
        mov     [ebp+NTFS.cur_index_buf], eax
1509
        mov     [ebp+NTFS.cur_index_buf], eax
1510
        add     eax, [esi+indexRecordSize]
1510
        add     eax, [esi+indexRecordSize]
1511
        mov     [ebp+NTFS.secondIndexBuffer], eax
1511
        mov     [ebp+NTFS.secondIndexBuffer], eax
1512
        mov     [ebp+NTFS.cur_index_size], edi
1512
        mov     [ebp+NTFS.cur_index_size], edi
1513
        stdcall kernel_free, edx
1513
        stdcall kernel_free, edx
1514
        jmp     .doit
1514
        jmp     .doit
1515
 
1515
 
1516
.dump_root_done:
1516
.dump_root_done:
1517
; now dump all subnodes
1517
; now dump all subnodes
1518
        push    ecx edi
1518
        push    ecx edi
1519
        lea     edi, [ebp+NTFS.bitmap_buf]
1519
        lea     edi, [ebp+NTFS.bitmap_buf]
1520
        mov     [ebp+NTFS.cur_buf], edi
1520
        mov     [ebp+NTFS.cur_buf], edi
1521
        mov     ecx, 0x400/4
1521
        mov     ecx, 0x400/4
1522
        xor     eax, eax
1522
        xor     eax, eax
1523
        rep stosd
1523
        rep stosd
1524
        mov     [ebp+NTFS.cur_attr], 0xB0   ; $BITMAP
1524
        mov     [ebp+NTFS.cur_attr], 0xB0   ; $BITMAP
1525
        and     [ebp+NTFS.cur_offs], 0
1525
        and     [ebp+NTFS.cur_offs], 0
1526
        mov     [ebp+NTFS.cur_size], 2
1526
        mov     [ebp+NTFS.cur_size], 2
1527
        call    ntfs_read_attr.newAttribute
1527
        call    ntfs_read_attr.newAttribute
1528
        pop     edi ecx
1528
        pop     edi ecx
1529
        push    0       ; save offset in $BITMAP attribute
1529
        push    0       ; save offset in $BITMAP attribute
1530
        and     [ebp+NTFS.cur_offs], 0
1530
        and     [ebp+NTFS.cur_offs], 0
1531
.dumploop:
1531
.dumploop:
1532
        mov     [ebp+NTFS.cur_attr], 0xA0
1532
        mov     [ebp+NTFS.cur_attr], 0xA0
1533
        mov     eax, [ebp+NTFS.cur_subnode_size]
1533
        mov     eax, [ebp+NTFS.cur_subnode_size]
1534
        mov     [ebp+NTFS.cur_size], eax
1534
        mov     [ebp+NTFS.cur_size], eax
1535
        mov     esi, [ebp+NTFS.cur_index_buf]
1535
        mov     esi, [ebp+NTFS.cur_index_buf]
1536
        mov     [ebp+NTFS.cur_buf], esi
1536
        mov     [ebp+NTFS.cur_buf], esi
1537
        mov     eax, [ebp+NTFS.cur_offs]
1537
        mov     eax, [ebp+NTFS.cur_offs]
1538
        push    eax
1538
        push    eax
1539
        imul    eax, [ebp+NTFS.cur_subnode_size]
1539
        imul    eax, [ebp+NTFS.cur_subnode_size]
1540
        mov     [ebp+NTFS.cur_offs], eax
1540
        mov     [ebp+NTFS.cur_offs], eax
1541
        call    ntfs_read_attr.newAttribute
1541
        call    ntfs_read_attr.newAttribute
1542
        pop     [ebp+NTFS.cur_offs]
1542
        pop     [ebp+NTFS.cur_offs]
1543
        mov     eax, [ebp+NTFS.cur_subnode_size]
1543
        mov     eax, [ebp+NTFS.cur_subnode_size]
1544
        shl     eax, 9
1544
        shl     eax, 9
1545
        cmp     [ebp+NTFS.cur_read], eax
1545
        cmp     [ebp+NTFS.cur_read], eax
1546
        jnz     .done
1546
        jnz     .done
1547
        push    eax
1547
        push    eax
1548
        mov     eax, [ebp+NTFS.cur_offs]
1548
        mov     eax, [ebp+NTFS.cur_offs]
1549
        and     eax, 0x400*8-1
1549
        and     eax, 0x400*8-1
1550
        bt      dword [ebp+NTFS.bitmap_buf], eax
1550
        bt      dword [ebp+NTFS.bitmap_buf], eax
1551
        pop     eax
1551
        pop     eax
1552
        jnc     .dump_subnode_done
1552
        jnc     .dump_subnode_done
1553
        cmp     dword [esi], 'INDX'
1553
        cmp     dword [esi], 'INDX'
1554
        jnz     .dump_subnode_done
1554
        jnz     .dump_subnode_done
1555
        push    ebx
1555
        push    ebx
1556
        mov     ebx, esi
1556
        mov     ebx, esi
1557
        call    ntfs_restore_usa
1557
        call    ntfs_restore_usa
1558
        pop     ebx
1558
        pop     ebx
1559
        jc      .dump_subnode_done
1559
        jc      .dump_subnode_done
1560
        add     esi, recordNode
1560
        add     esi, recordNode
1561
        add     esi, [esi+indexOffset]
1561
        add     esi, [esi+indexOffset]
1562
.dump_subnode:
1562
.dump_subnode:
1563
        test    byte [esi+indexFlags], 2
1563
        test    byte [esi+indexFlags], 2
1564
        jnz     .dump_subnode_done
1564
        jnz     .dump_subnode_done
1565
        call    .add_entry
1565
        call    .add_entry
1566
        movzx   eax, word [esi+indexAllocatedSize]
1566
        movzx   eax, word [esi+indexAllocatedSize]
1567
        add     esi, eax
1567
        add     esi, eax
1568
        jmp     .dump_subnode
1568
        jmp     .dump_subnode
1569
 
1569
 
1570
.dump_subnode_done:
1570
.dump_subnode_done:
1571
        inc     [ebp+NTFS.cur_offs]
1571
        inc     [ebp+NTFS.cur_offs]
1572
        test    [ebp+NTFS.cur_offs], 0x400*8-1
1572
        test    [ebp+NTFS.cur_offs], 0x400*8-1
1573
        jnz     .dumploop
1573
        jnz     .dumploop
1574
        mov     [ebp+NTFS.cur_attr], 0xB0
1574
        mov     [ebp+NTFS.cur_attr], 0xB0
1575
        push    ecx edi
1575
        push    ecx edi
1576
        lea     edi, [ebp+NTFS.bitmap_buf]
1576
        lea     edi, [ebp+NTFS.bitmap_buf]
1577
        mov     [ebp+NTFS.cur_buf], edi
1577
        mov     [ebp+NTFS.cur_buf], edi
1578
        mov     ecx, 0x400/4
1578
        mov     ecx, 0x400/4
1579
        xor     eax, eax
1579
        xor     eax, eax
1580
        rep stosd
1580
        rep stosd
1581
        pop     edi ecx
1581
        pop     edi ecx
1582
        pop     eax
1582
        pop     eax
1583
        push    [ebp+NTFS.cur_offs]
1583
        push    [ebp+NTFS.cur_offs]
1584
        inc     eax
1584
        inc     eax
1585
        mov     [ebp+NTFS.cur_offs], eax
1585
        mov     [ebp+NTFS.cur_offs], eax
1586
        mov     [ebp+NTFS.cur_size], 2
1586
        mov     [ebp+NTFS.cur_size], 2
1587
        push    eax
1587
        push    eax
1588
        call    ntfs_read_attr.newAttribute
1588
        call    ntfs_read_attr.newAttribute
1589
        pop     eax
1589
        pop     eax
1590
        pop     [ebp+NTFS.cur_offs]
1590
        pop     [ebp+NTFS.cur_offs]
1591
        push    eax
1591
        push    eax
1592
        jmp     .dumploop
1592
        jmp     .dumploop
1593
 
1593
 
1594
.done:
1594
.done:
1595
        pop     eax
1595
        pop     eax
1596
        pop     eax
1596
        pop     eax
1597
        mov     ebx, [eax+4]
1597
        mov     ebx, [eax+4]
1598
        pop     eax
1598
        pop     eax
1599
        pop     eax
1599
        pop     eax
1600
        test    eax, eax
1600
        test    eax, eax
1601
        jz      .ret
1601
        jz      .ret
1602
        xor     eax, eax
1602
        xor     eax, eax
1603
        dec     ecx
1603
        dec     ecx
1604
        js      @f
1604
        js      @f
1605
        mov     al, ERROR_END_OF_FILE
1605
        mov     al, ERROR_END_OF_FILE
1606
@@:
1606
@@:
1607
        push    eax
1607
        push    eax
1608
        call    ntfs_unlock
1608
        call    ntfs_unlock
1609
        pop     eax
1609
        pop     eax
1610
        ret
1610
        ret
1611
 
1611
 
1612
.add_special_entry:
1612
.add_special_entry:
1613
        mov     eax, [edx]
1613
        mov     eax, [edx]
1614
        inc     dword [eax+8]   ; new file found
1614
        inc     dword [eax+8]   ; new file found
1615
        dec     ebx
1615
        dec     ebx
1616
        jns     .ret
1616
        jns     .ret
1617
        dec     ecx
1617
        dec     ecx
1618
        js      .ret
1618
        js      .ret
1619
        inc     dword [eax+4]   ; new file block copied
1619
        inc     dword [eax+4]   ; new file block copied
1620
        mov     eax, [edx+4]
1620
        mov     eax, [edx+4]
1621
        mov     [edi+4], eax
1621
        mov     [edi+4], eax
1622
        mov     eax, 0x10
1622
        mov     eax, 0x10
1623
        stosd
1623
        stosd
1624
        scasd
1624
        scasd
1625
        push    ebx ecx edx
1625
        push    ebx ecx edx
1626
        mov     eax, dword [ebp+NTFS.bitmap_buf]
1626
        mov     eax, dword [ebp+NTFS.bitmap_buf]
1627
        mov     edx, dword [ebp+NTFS.bitmap_buf+4]
1627
        mov     edx, dword [ebp+NTFS.bitmap_buf+4]
1628
        call    ntfs_datetime_to_bdfe
1628
        call    ntfs_datetime_to_bdfe
1629
        mov     eax, dword [ebp+NTFS.bitmap_buf+0x18]
1629
        mov     eax, dword [ebp+NTFS.bitmap_buf+0x18]
1630
        mov     edx, dword [ebp+NTFS.bitmap_buf+0x1C]
1630
        mov     edx, dword [ebp+NTFS.bitmap_buf+0x1C]
1631
        call    ntfs_datetime_to_bdfe
1631
        call    ntfs_datetime_to_bdfe
1632
        mov     eax, dword [ebp+NTFS.bitmap_buf+8]
1632
        mov     eax, dword [ebp+NTFS.bitmap_buf+8]
1633
        mov     edx, dword [ebp+NTFS.bitmap_buf+0xC]
1633
        mov     edx, dword [ebp+NTFS.bitmap_buf+0xC]
1634
        call    ntfs_datetime_to_bdfe
1634
        call    ntfs_datetime_to_bdfe
1635
        pop     edx ecx ebx
1635
        pop     edx ecx ebx
1636
        xor     eax, eax
1636
        xor     eax, eax
1637
        stosd
1637
        stosd
1638
        stosd
1638
        stosd
1639
        mov     al, '.'
1639
        mov     al, '.'
1640
        push    edi ecx
1640
        push    edi ecx
1641
        lea     ecx, [esi+1]
1641
        lea     ecx, [esi+1]
1642
        cmp     dword[edi-36], 2
1642
        cmp     dword[edi-36], 2
1643
        jz      .utf16sp
1643
        jz      .utf16sp
1644
        rep stosb
1644
        rep stosb
1645
        mov     byte [edi], 0
1645
        mov     byte [edi], 0
1646
        pop     ecx edi
1646
        pop     ecx edi
1647
        cmp     dword[edi-36], 3
1647
        cmp     dword[edi-36], 3
1648
        jz      @f
1648
        jz      @f
1649
        add     edi, 264
1649
        add     edi, 264
1650
        ret
1650
        ret
1651
 
1651
 
1652
.utf16sp:
1652
.utf16sp:
1653
        rep stosw
1653
        rep stosw
1654
        mov     word [edi], 0
1654
        mov     word [edi], 0
1655
        pop     ecx edi
1655
        pop     ecx edi
1656
@@:
1656
@@:
1657
        add     edi, 520
1657
        add     edi, 520
1658
.ret:
1658
.ret:
1659
        ret
1659
        ret
1660
 
1660
 
1661
.add_entry:
1661
.add_entry:
1662
; do not return DOS 8.3 names
1662
; do not return DOS 8.3 names
1663
        cmp     byte [esi+namespace], 2
1663
        cmp     byte [esi+namespace], 2
1664
        jz      .ret
1664
        jz      .ret
1665
; do not return system files
1665
; do not return system files
1666
        cmp     dword[esi+fileRecordReference], 16
1666
        cmp     dword[esi+fileRecordReference], 16
1667
        jb      .ret
1667
        jb      .ret
1668
        cmp     byte [esi+fileNameLength], 0
1668
        cmp     byte [esi+fileNameLength], 0
1669
        jz      .ret
1669
        jz      .ret
1670
        mov     eax, [edx]
1670
        mov     eax, [edx]
1671
        inc     dword [eax+8]   ; new file found
1671
        inc     dword [eax+8]   ; new file found
1672
        dec     ebx
1672
        dec     ebx
1673
        jns     .ret
1673
        jns     .ret
1674
        dec     ecx
1674
        dec     ecx
1675
        js      .ret
1675
        js      .ret
1676
        inc     dword [eax+4]   ; new file block copied
1676
        inc     dword [eax+4]   ; new file block copied
1677
        mov     eax, [edx+4]    ; flags
1677
        mov     eax, [edx+4]    ; flags
1678
        call    ntfs_direntry_to_bdfe
1678
        call    ntfs_direntry_to_bdfe
1679
        push    ecx esi edi
1679
        push    ecx esi edi
1680
        movzx   ecx, byte [esi+fileNameLength]
1680
        movzx   ecx, byte [esi+fileNameLength]
1681
        add     esi, fileName
1681
        add     esi, fileName
1682
        cmp     dword[edi-36], 2
1682
        cmp     dword[edi-36], 2
1683
        jz      .utf16
1683
        jz      .utf16
1684
        cmp     dword[edi-36], 3
1684
        cmp     dword[edi-36], 3
1685
        jz      .utf8
1685
        jz      .utf8
1686
@@:
1686
@@:
1687
        lodsw
1687
        lodsw
1688
        call    uni2ansi_char
1688
        call    uni2ansi_char
1689
        stosb
1689
        stosb
1690
        loop    @b
1690
        loop    @b
1691
        mov     byte [edi], 0
1691
        mov     byte [edi], 0
1692
        pop     edi esi ecx
1692
        pop     edi esi ecx
1693
        add     edi, 264
1693
        add     edi, 264
1694
        ret
1694
        ret
1695
 
1695
 
1696
.utf8:
1696
.utf8:
1697
        push    ecx
1697
        push    ecx
1698
        mov     cx, 519
1698
        mov     cx, 519
1699
@@:
1699
@@:
1700
        lodsw
1700
        lodsw
1701
        call    UTF16to8
1701
        call    UTF16to8
1702
        js      @f
1702
        js      @f
1703
        dec     dword[esp]
1703
        dec     dword[esp]
1704
        jnz     @b
1704
        jnz     @b
1705
@@:
1705
@@:
1706
        mov     byte [edi], 0
1706
        mov     byte [edi], 0
1707
        pop     edi
1707
        pop     edi
1708
@@:
1708
@@:
1709
        pop     edi esi ecx
1709
        pop     edi esi ecx
1710
        add     edi, 520
1710
        add     edi, 520
1711
        ret
1711
        ret
1712
 
1712
 
1713
.utf16:
1713
.utf16:
1714
        rep movsw
1714
        rep movsw
1715
        mov     word [edi], 0
1715
        mov     word [edi], 0
1716
        jmp     @b
1716
        jmp     @b
1717
 
1717
 
1718
ntfs_direntry_to_bdfe:
1718
ntfs_direntry_to_bdfe:
1719
        mov     [edi+4], eax    ; ANSI/UNICODE name
1719
        mov     [edi+4], eax    ; ANSI/UNICODE name
1720
        mov     eax, [esi+fileFlags]
1720
        mov     eax, [esi+fileFlags]
1721
        test    eax, 0x10000000
1721
        test    eax, 0x10000000
1722
        jz      @f
1722
        jz      @f
1723
        and     eax, not 0x10000000
1723
        and     eax, not 0x10000000
1724
        or      al, 0x10
1724
        or      al, 0x10
1725
@@:
1725
@@:
1726
        stosd
1726
        stosd
1727
        scasd
1727
        scasd
1728
        push    ebx ecx edx
1728
        push    ebx ecx edx
1729
        mov     eax, [esi+fileCreated]
1729
        mov     eax, [esi+fileCreated]
1730
        mov     edx, [esi+fileCreated+4]
1730
        mov     edx, [esi+fileCreated+4]
1731
        call    ntfs_datetime_to_bdfe
1731
        call    ntfs_datetime_to_bdfe
1732
        mov     eax, [esi+fileAccessed]
1732
        mov     eax, [esi+fileAccessed]
1733
        mov     edx, [esi+fileAccessed+4]
1733
        mov     edx, [esi+fileAccessed+4]
1734
        call    ntfs_datetime_to_bdfe
1734
        call    ntfs_datetime_to_bdfe
1735
        mov     eax, [esi+fileModified]
1735
        mov     eax, [esi+fileModified]
1736
        mov     edx, [esi+fileModified+4]
1736
        mov     edx, [esi+fileModified+4]
1737
        call    ntfs_datetime_to_bdfe
1737
        call    ntfs_datetime_to_bdfe
1738
        pop     edx ecx ebx
1738
        pop     edx ecx ebx
1739
        mov     eax, [esi+fileRealSize]
1739
        mov     eax, [esi+fileRealSize]
1740
        stosd
1740
        stosd
1741
        mov     eax, [esi+fileRealSize+4]
1741
        mov     eax, [esi+fileRealSize+4]
1742
        stosd
1742
        stosd
1743
        ret
1743
        ret
1744
 
1744
 
1745
ntfs_datetime_to_bdfe:
1745
ntfs_datetime_to_bdfe:
1746
; in: edx:eax = seconds since 01.01.1601 x10000000
1746
; in: edx:eax = seconds since 01.01.1601 x10000000
1747
; edi -> data block
1747
; edi -> data block
1748
; out: edi = edi+8
1748
; out: edi = edi+8
1749
        sub     eax, 3365781504
1749
        sub     eax, 3365781504
1750
        sbb     edx, 29389701
1750
        sbb     edx, 29389701
1751
        mov     ecx, 10000000
1751
        mov     ecx, 10000000
1752
        cmp     edx, ecx
1752
        cmp     edx, ecx
1753
        jc      @f
1753
        jc      @f
1754
        xor     edx, edx
1754
        xor     edx, edx
1755
@@:
1755
@@:
1756
        div     ecx
1756
        div     ecx
1757
        jmp     fsTime2bdfe
1757
        jmp     fsTime2bdfe
1758
 
1758
 
1759
;----------------------------------------------------------------
1759
;----------------------------------------------------------------
1760
ntfs_GetFileInfo:
1760
ntfs_GetFileInfo:
1761
        mov     edi, [ebx+16]
1761
        mov     edi, [ebx+16]
1762
        cmp     byte [esi], 0
1762
        cmp     byte [esi], 0
1763
        jz      .volume
1763
        jz      .volume
1764
        call    ntfs_lock
1764
        call    ntfs_lock
1765
        call    ntfs_find_lfn
1765
        call    ntfs_find_lfn
1766
        jnc     .found
1766
        jnc     .found
1767
        test    eax, eax
1767
        test    eax, eax
1768
        jz      ntfsFail
1768
        jz      ntfsFail
1769
        jmp     ntfsNotFound
1769
        jmp     ntfsNotFound
1770
 
1770
 
1771
.found:
1771
.found:
1772
        mov     esi, eax
1772
        mov     esi, eax
1773
        xor     eax, eax
1773
        xor     eax, eax
1774
        call    ntfs_direntry_to_bdfe
1774
        call    ntfs_direntry_to_bdfe
1775
.end:
1775
.end:
1776
        call    ntfs_unlock
1776
        call    ntfs_unlock
1777
        xor     eax, eax
1777
        xor     eax, eax
1778
@@:
1778
@@:
1779
        ret
1779
        ret
1780
 
1780
 
1781
.volume:
1781
.volume:
1782
        mov     eax, dword [ebp+NTFS.Length]
1782
        mov     eax, dword [ebp+NTFS.Length]
1783
        mov     edx, dword [ebp+NTFS.Length+4]
1783
        mov     edx, dword [ebp+NTFS.Length+4]
1784
        shld    edx, eax, 9
1784
        shld    edx, eax, 9
1785
        shl     eax, 9
1785
        shl     eax, 9
1786
        mov     [edi+36], edx
1786
        mov     [edi+36], edx
1787
        mov     [edi+32], eax
1787
        mov     [edi+32], eax
1788
        mov     eax, [ebx+8]
1788
        mov     eax, [ebx+8]
1789
        mov     byte [edi], 8
1789
        mov     byte [edi], 8
1790
        mov     [edi+4], eax
1790
        mov     [edi+4], eax
1791
        test    eax, eax
1791
        test    eax, eax
1792
        jz      @b
1792
        jz      @b
1793
        call    ntfs_lock
1793
        call    ntfs_lock
1794
        add     edi, 40
1794
        add     edi, 40
1795
        mov     [ebp+NTFS.cur_buf], edi
1795
        mov     [ebp+NTFS.cur_buf], edi
1796
        mov     [ebp+NTFS.cur_iRecord], 3
1796
        mov     [ebp+NTFS.cur_iRecord], 3
1797
        mov     [ebp+NTFS.cur_attr], 0x60
1797
        mov     [ebp+NTFS.cur_attr], 0x60
1798
        mov     [ebp+NTFS.cur_offs], 0
1798
        mov     [ebp+NTFS.cur_offs], 0
1799
        mov     [ebp+NTFS.cur_size], 1
1799
        mov     [ebp+NTFS.cur_size], 1
1800
        call    ntfs_read_attr
1800
        call    ntfs_read_attr
1801
        jc      ntfsFail
1801
        jc      ntfsFail
1802
        mov     ecx, [ebp+NTFS.cur_read]
1802
        mov     ecx, [ebp+NTFS.cur_read]
1803
        mov     [edi+ecx], ax
1803
        mov     [edi+ecx], ax
1804
        cmp     byte [ebx+8], 2
1804
        cmp     byte [ebx+8], 2
1805
        jz      .end
1805
        jz      .end
1806
        shr     ecx, 1
1806
        shr     ecx, 1
1807
        jz      .end
1807
        jz      .end
1808
        mov     esi, edi
1808
        mov     esi, edi
1809
        cmp     byte [ebx+8], 3
1809
        cmp     byte [ebx+8], 3
1810
        jnz     @f
1810
        jnz     @f
1811
        shl     ecx, 1
1811
        shl     ecx, 1
1812
        call    UTF16to8_string
1812
        call    UTF16to8_string
1813
        mov     byte [edi], 0
1813
        mov     byte [edi], 0
1814
        jmp     .end
1814
        jmp     .end
1815
 
1815
 
1816
@@:
1816
@@:
1817
        lodsw
1817
        lodsw
1818
        call    uni2ansi_char
1818
        call    uni2ansi_char
1819
        stosb
1819
        stosb
1820
        loop    @b
1820
        loop    @b
1821
        mov     byte [edi], 0
1821
        mov     byte [edi], 0
1822
        jmp     .end
1822
        jmp     .end
1823
 
1823
 
1824
;----------------------------------------------------------------
1824
;----------------------------------------------------------------
1825
ntfs_CreateFolder:
1825
ntfs_CreateFolder:
1826
        mov     [ebp+NTFS.bFolder], 1
1826
        mov     [ebp+NTFS.bFolder], 1
1827
        jmp     @f
1827
        jmp     @f
1828
 
1828
 
1829
ntfs_CreateFile:
1829
ntfs_CreateFile:
1830
        mov     [ebp+NTFS.bFolder], 0
1830
        mov     [ebp+NTFS.bFolder], 0
1831
@@: ; 1. Search file
1831
@@: ; 1. Search file
1832
        call    ntfs_lock
1832
        call    ntfs_lock
1833
        call    ntfs_find_lfn
1833
        call    ntfs_find_lfn
1834
        jc      .notFound
1834
        jc      .notFound
1835
; found, rewrite
1835
; found, rewrite
1836
        cmp     [ebp+NTFS.cur_iRecord], 16
1836
        cmp     [ebp+NTFS.cur_iRecord], 16
1837
        jc      ntfsDenied
1837
        jc      ntfsDenied
1838
        cmp     [ebp+NTFS.bFolder], 1
1838
        cmp     [ebp+NTFS.bFolder], 1
1839
        jz      .folder
1839
        jz      .folder
1840
        test    byte [eax+fileFlags], 1
1840
        test    byte [eax+fileFlags], 1
1841
        jnz     ntfsDenied
1841
        jnz     ntfsDenied
1842
        cmp     [ebp+NTFS.fragmentCount], 1
1842
        cmp     [ebp+NTFS.fragmentCount], 1
1843
        jnz     ntfsUnsupported     ; record fragmented
1843
        jnz     ntfsUnsupported     ; record fragmented
1844
; edit directory node
1844
; edit directory node
1845
        mov     edi, [ebp+NTFS.cur_index_buf]
1845
        mov     edi, [ebp+NTFS.cur_index_buf]
1846
        cmp     dword [edi], 'INDX'
1846
        cmp     dword [edi], 'INDX'
1847
        jz      @f
1847
        jz      @f
1848
        mov     esi, [ebp+NTFS.frs_buffer]
1848
        mov     esi, [ebp+NTFS.frs_buffer]
1849
        mov     ecx, [esi+recordRealSize]
1849
        mov     ecx, [esi+recordRealSize]
1850
        shr     ecx, 2
1850
        shr     ecx, 2
1851
        rep movsd
1851
        rep movsd
1852
        mov     esi, [ebp+NTFS.attr_offs]
1852
        mov     esi, [ebp+NTFS.attr_offs]
1853
        mov     cl, [esi+attributeOffset]
1853
        mov     cl, [esi+attributeOffset]
1854
        sub     esi, [ebp+NTFS.frs_buffer]
1854
        sub     esi, [ebp+NTFS.frs_buffer]
1855
        add     eax, ecx
1855
        add     eax, ecx
1856
        add     eax, esi
1856
        add     eax, esi
1857
@@:
1857
@@:
1858
        mov     edi, eax
1858
        mov     edi, eax
1859
        mov     eax, [ebx+12]
1859
        mov     eax, [ebx+12]
1860
        mov     [edi+fileRealSize], eax
1860
        mov     [edi+fileRealSize], eax
1861
        mov     dword [edi+fileRealSize+4], 0
1861
        mov     dword [edi+fileRealSize+4], 0
1862
        push    ebx eax
1862
        push    ebx eax
1863
        call    ntfsGetTime
1863
        call    ntfsGetTime
1864
        mov     [edi+fileModified], eax
1864
        mov     [edi+fileModified], eax
1865
        mov     [edi+fileModified+4], edx
1865
        mov     [edi+fileModified+4], edx
1866
        mov     [edi+recordModified], eax
1866
        mov     [edi+recordModified], eax
1867
        mov     [edi+recordModified+4], edx
1867
        mov     [edi+recordModified+4], edx
1868
        mov     [edi+fileAccessed], eax
1868
        mov     [edi+fileAccessed], eax
1869
        mov     [edi+fileAccessed+4], edx
1869
        mov     [edi+fileAccessed+4], edx
1870
        pop     edx ebx
1870
        pop     edx ebx
1871
        mov     eax, [ebp+NTFS.LastRead]
1871
        mov     eax, [ebp+NTFS.LastRead]
1872
        mov     [ebp+NTFS.nodeLastRead], eax
1872
        mov     [ebp+NTFS.nodeLastRead], eax
1873
        mov     [ebp+NTFS.cur_attr], 0x80
1873
        mov     [ebp+NTFS.cur_attr], 0x80
1874
        mov     [ebp+NTFS.cur_offs], 0
1874
        mov     [ebp+NTFS.cur_offs], 0
1875
        mov     [ebp+NTFS.cur_size], 0
1875
        mov     [ebp+NTFS.cur_size], 0
1876
        call    ntfs_read_attr
1876
        call    ntfs_read_attr
1877
        jc      ntfsFail
1877
        jc      ntfsFail
1878
        mov     esi, edi
1878
        mov     esi, edi
1879
        mov     edi, [ebp+NTFS.frs_buffer]
1879
        mov     edi, [ebp+NTFS.frs_buffer]
1880
        cmp     word [edi+baseRecordReuse], 0
1880
        cmp     word [edi+baseRecordReuse], 0
1881
        jnz     ntfsUnsupported     ; auxiliary record
1881
        jnz     ntfsUnsupported     ; auxiliary record
1882
        mov     al, [edi+attributeOffset]
1882
        mov     al, [edi+attributeOffset]
1883
        add     edi, eax
1883
        add     edi, eax
1884
        mov     al, [edi+attributeOffset]
1884
        mov     al, [edi+attributeOffset]
1885
        add     edi, eax
1885
        add     edi, eax
1886
        mov     ecx, 6
1886
        mov     ecx, 6
1887
        add     esi, fileModified
1887
        add     esi, fileModified
1888
        add     edi, 8
1888
        add     edi, 8
1889
        rep movsd
1889
        rep movsd
1890
        mov     eax, edx
1890
        mov     eax, edx
1891
        xor     edx, edx
1891
        xor     edx, edx
1892
        mov     ecx, [ebp+NTFS.attr_offs]
1892
        mov     ecx, [ebp+NTFS.attr_offs]
1893
        cmp     word [ecx+attributeFlags], 0
1893
        cmp     word [ecx+attributeFlags], 0
1894
        jnz     ntfsUnsupported
1894
        jnz     ntfsUnsupported
1895
        push    ebx
1895
        push    ebx
1896
        cmp     byte [ecx+nonResidentFlag], 0
1896
        cmp     byte [ecx+nonResidentFlag], 0
1897
        jz      @f
1897
        jz      @f
1898
        cmp     [ecx+attributeRealSize+4], edx
1898
        cmp     [ecx+attributeRealSize+4], edx
1899
        jnz     @f
1899
        jnz     @f
1900
        cmp     [ecx+attributeRealSize], eax
1900
        cmp     [ecx+attributeRealSize], eax
1901
        jz      ntfs_WriteFile.writeNode
1901
        jz      ntfs_WriteFile.writeNode
1902
@@:
1902
@@:
1903
        jmp     ntfs_WriteFile.resizeAttribute
1903
        jmp     ntfs_WriteFile.resizeAttribute
1904
 
1904
 
1905
.folder:
1905
.folder:
1906
        bt      dword [eax+fileFlags], 28
1906
        bt      dword [eax+fileFlags], 28
1907
        jnc     ntfsDenied
1907
        jnc     ntfsDenied
1908
        push    0
1908
        push    0
1909
        jmp     ntfsOut
1909
        jmp     ntfsOut
1910
 
1910
 
1911
.notFound:  ; create
1911
.notFound:  ; create
1912
        test    eax, eax
1912
        test    eax, eax
1913
        jz      ntfsFail
1913
        jz      ntfsFail
1914
        cmp     [ebp+NTFS.fragmentCount], 1
1914
        cmp     [ebp+NTFS.fragmentCount], 1
1915
        jnz     ntfsUnsupported     ; record fragmented
1915
        jnz     ntfsUnsupported     ; record fragmented
1916
; 2. Prepare directory record
1916
; 2. Prepare directory record
1917
        mov     edi, esi
1917
        mov     edi, esi
1918
        mov     edx, eax
1918
        mov     edx, eax
1919
        xor     ecx, ecx
1919
        xor     ecx, ecx
1920
@@:         ; count characters
1920
@@:         ; count characters
1921
        call    utf8to16
1921
        call    utf8to16
1922
        cmp     ax, '/'
1922
        cmp     ax, '/'
1923
        jz      ntfsNotFound    ; path folder not found
1923
        jz      ntfsNotFound    ; path folder not found
1924
        inc     ecx
1924
        inc     ecx
1925
        test    ax, ax
1925
        test    ax, ax
1926
        jnz     @b
1926
        jnz     @b
1927
        dec     ecx
1927
        dec     ecx
1928
        push    ecx     ; name length in chars
1928
        push    ecx     ; name length in chars
1929
        push    edi
1929
        push    edi
1930
        shl     ecx, 1
1930
        shl     ecx, 1
1931
        add     ecx, fileName+7
1931
        add     ecx, fileName+7
1932
        and     ecx, not 7
1932
        and     ecx, not 7
1933
        mov     edi, [ebp+NTFS.cur_index_buf]
1933
        mov     edi, [ebp+NTFS.cur_index_buf]
1934
        mov     eax, [ebx+12]
1934
        mov     eax, [ebx+12]
1935
        mov     [ebp+NTFS.fileRealSize], eax
1935
        mov     [ebp+NTFS.fileRealSize], eax
1936
        mov     eax, [ebx+16]
1936
        mov     eax, [ebx+16]
1937
        mov     [ebp+NTFS.fileDataBuffer], eax
1937
        mov     [ebp+NTFS.fileDataBuffer], eax
1938
        push    ecx     ; index length
1938
        push    ecx     ; index length
1939
        mov     eax, edx
1939
        mov     eax, edx
1940
        mov     edx, ecx
1940
        mov     edx, ecx
1941
        cmp     dword [edi], 'INDX'
1941
        cmp     dword [edi], 'INDX'
1942
        jz      .indexRecord
1942
        jz      .indexRecord
1943
        mov     esi, [ebp+NTFS.frs_buffer]  ; indexRoot
1943
        mov     esi, [ebp+NTFS.frs_buffer]  ; indexRoot
1944
        mov     ecx, [esi+recordRealSize]
1944
        mov     ecx, [esi+recordRealSize]
1945
        add     edx, ecx
1945
        add     edx, ecx
1946
        cmp     [esi+recordAllocatedSize], edx
1946
        cmp     [esi+recordAllocatedSize], edx
1947
        jc      .growTree
1947
        jc      .growTree
1948
        mov     [esi+recordRealSize], edx
1948
        mov     [esi+recordRealSize], edx
1949
        shr     ecx, 2
1949
        shr     ecx, 2
1950
        rep movsd
1950
        rep movsd
1951
        mov     edi, [ebp+NTFS.indexRoot]
1951
        mov     edi, [ebp+NTFS.indexRoot]
1952
        sub     edi, [ebp+NTFS.frs_buffer]
1952
        sub     edi, [ebp+NTFS.frs_buffer]
1953
        add     edi, [ebp+NTFS.cur_index_buf]
1953
        add     edi, [ebp+NTFS.cur_index_buf]
1954
        mov     esi, [esp]
1954
        mov     esi, [esp]
1955
        add     [edi+sizeWithHeader], esi
1955
        add     [edi+sizeWithHeader], esi
1956
        add     [edi+sizeWithoutHeader], esi
1956
        add     [edi+sizeWithoutHeader], esi
1957
        mov     cl, [edi+attributeOffset]
1957
        mov     cl, [edi+attributeOffset]
1958
        add     edi, ecx
1958
        add     edi, ecx
1959
        add     [edi+rootNode+nodeRealSize], esi
1959
        add     [edi+rootNode+nodeRealSize], esi
1960
        add     [edi+rootNode+nodeAllocatedSize], esi
1960
        add     [edi+rootNode+nodeAllocatedSize], esi
1961
        sub     eax, [ebp+NTFS.cur_index_buf]
1961
        sub     eax, [ebp+NTFS.cur_index_buf]
1962
        add     eax, edi
1962
        add     eax, edi
1963
        mov     edi, [ebp+NTFS.cur_index_buf]
1963
        mov     edi, [ebp+NTFS.cur_index_buf]
1964
        jmp     .common
1964
        jmp     .common
1965
 
1965
 
1966
.growTree:  ; create indexRecord
1966
.growTree:  ; create indexRecord
1967
        mov     edi, [ebp+NTFS.cur_index_buf]
1967
        mov     edi, [ebp+NTFS.cur_index_buf]
1968
        mov     ecx, 10
1968
        mov     ecx, 10
1969
        xor     eax, eax
1969
        xor     eax, eax
1970
        rep stosd
1970
        rep stosd
1971
        mov     esi, [ebp+NTFS.indexRoot]
1971
        mov     esi, [ebp+NTFS.indexRoot]
1972
        mov     al, [esi+attributeOffset]
1972
        mov     al, [esi+attributeOffset]
1973
        add     esi, eax
1973
        add     esi, eax
1974
        rdtsc
1974
        rdtsc
1975
        stosw
1975
        stosw
1976
        mov     eax, [esi+indexRecordSize]
1976
        mov     eax, [esi+indexRecordSize]
1977
        cmp     eax, [ebp+NTFS.frs_size]
1977
        cmp     eax, [ebp+NTFS.frs_size]
1978
        jc      .errorPop3
1978
        jc      .errorPop3
1979
        shr     eax, 9
1979
        shr     eax, 9
1980
        inc     eax
1980
        inc     eax
1981
        mov     edi, [ebp+NTFS.cur_index_buf]
1981
        mov     edi, [ebp+NTFS.cur_index_buf]
1982
        mov     dword[edi], 'INDX'
1982
        mov     dword[edi], 'INDX'
1983
        mov     byte [edi+updateSequenceOffset], 28h
1983
        mov     byte [edi+updateSequenceOffset], 28h
1984
        mov     [edi+updateSequenceSize], al
1984
        mov     [edi+updateSequenceSize], al
1985
        add     edi, recordNode
1985
        add     edi, recordNode
1986
        shl     eax, 1
1986
        shl     eax, 1
1987
        add     eax, 28h-recordNode+7
1987
        add     eax, 28h-recordNode+7
1988
        and     eax, not 7
1988
        and     eax, not 7
1989
        mov     [edi+indexOffset], eax
1989
        mov     [edi+indexOffset], eax
1990
        mov     ecx, [esi+indexRecordSize]
1990
        mov     ecx, [esi+indexRecordSize]
1991
        sub     ecx, recordNode
1991
        sub     ecx, recordNode
1992
        mov     [edi+nodeAllocatedSize], ecx
1992
        mov     [edi+nodeAllocatedSize], ecx
1993
        add     esi, rootNode
1993
        add     esi, rootNode
1994
        push    esi
1994
        push    esi
1995
        mov     ecx, [esi+nodeRealSize]
1995
        mov     ecx, [esi+nodeRealSize]
1996
        sub     ecx, [esi+indexOffset]
1996
        sub     ecx, [esi+indexOffset]
1997
        add     eax, ecx
1997
        add     eax, ecx
1998
        mov     [edi+nodeRealSize], eax
1998
        mov     [edi+nodeRealSize], eax
1999
        mov     eax, [esi+nonLeafFlag]
1999
        mov     eax, [esi+nonLeafFlag]
2000
        mov     [edi+nonLeafFlag], eax
2000
        mov     [edi+nonLeafFlag], eax
2001
        shr     ecx, 2
2001
        shr     ecx, 2
2002
        add     esi, [esi+indexOffset]
2002
        add     esi, [esi+indexOffset]
2003
        add     edi, [edi+indexOffset]
2003
        add     edi, [edi+indexOffset]
2004
        rep movsd       ; copy root indexes
2004
        rep movsd       ; copy root indexes
2005
; clear root node
2005
; clear root node
2006
        mov     cl, 10
2006
        mov     cl, 10
2007
        mov     edi, [esp]
2007
        mov     edi, [esp]
2008
        xor     eax, eax
2008
        xor     eax, eax
2009
        rep stosd
2009
        rep stosd
2010
        pop     edi
2010
        pop     edi
2011
        mov     byte [edi+indexOffset], 16
2011
        mov     byte [edi+indexOffset], 16
2012
        mov     byte [edi+nodeRealSize], 28h
2012
        mov     byte [edi+nodeRealSize], 28h
2013
        mov     byte [edi+nodeAllocatedSize], 28h
2013
        mov     byte [edi+nodeAllocatedSize], 28h
2014
        mov     byte [edi+nonLeafFlag], 1
2014
        mov     byte [edi+nonLeafFlag], 1
2015
        mov     byte [edi+16+indexAllocatedSize], 18h
2015
        mov     byte [edi+16+indexAllocatedSize], 18h
2016
        mov     byte [edi+16+indexFlags], 3
2016
        mov     byte [edi+16+indexFlags], 3
2017
        mov     esi, [ebp+NTFS.indexRoot]
2017
        mov     esi, [ebp+NTFS.indexRoot]
2018
        add     edi, 28h
2018
        add     edi, 28h
2019
        mov     eax, edi
2019
        mov     eax, edi
2020
        sub     eax, esi
2020
        sub     eax, esi
2021
        mov     word [esi+sizeWithoutHeader], 38h
2021
        mov     word [esi+sizeWithoutHeader], 38h
2022
        xchg    [esi+sizeWithHeader], eax
2022
        xchg    [esi+sizeWithHeader], eax
2023
        add     esi, eax
2023
        add     esi, eax
2024
        mov     [ebp+NTFS.attr_offs], edi
2024
        mov     [ebp+NTFS.attr_offs], edi
2025
        cmp     byte [esi], 0xA0
2025
        cmp     byte [esi], 0xA0
2026
        jnz     @f
2026
        jnz     @f
2027
        cmp     dword [esi+attributeAllocatedSize], 0
2027
        cmp     dword [esi+attributeAllocatedSize], 0
2028
        jz      @f
2028
        jz      @f
2029
        mov     eax, [ebp+NTFS.frs_buffer]
2029
        mov     eax, [ebp+NTFS.frs_buffer]
2030
        mov     ecx, eax
2030
        mov     ecx, eax
2031
        add     ecx, [eax+recordRealSize]
2031
        add     ecx, [eax+recordRealSize]
2032
        sub     ecx, esi
2032
        sub     ecx, esi
2033
        shr     ecx, 2
2033
        shr     ecx, 2
2034
        rep movsd
2034
        rep movsd
2035
        sub     edi, eax
2035
        sub     edi, eax
2036
        mov     [eax+recordRealSize], edi
2036
        mov     [eax+recordRealSize], edi
2037
        call    .ntfsNodeAlloc
2037
        call    .ntfsNodeAlloc
2038
        jc      ntfsErrorPop3
2038
        jc      ntfsErrorPop3
2039
        mov     eax, [ebp+NTFS.newRecord]
2039
        mov     eax, [ebp+NTFS.newRecord]
2040
        mov     edi, [ebp+NTFS.cur_index_buf]
2040
        mov     edi, [ebp+NTFS.cur_index_buf]
2041
        mov     [edi+recordVCN], eax
2041
        mov     [edi+recordVCN], eax
2042
        mov     edi, [ebp+NTFS.attr_offs]
2042
        mov     edi, [ebp+NTFS.attr_offs]
2043
        mov     [edi-8], eax
2043
        mov     [edi-8], eax
2044
        jmp     .refresh
2044
        jmp     .refresh
2045
 
2045
 
2046
@@:
2046
@@:
2047
        mov     cl, 32
2047
        mov     cl, 32
2048
        xor     eax, eax
2048
        xor     eax, eax
2049
        rep stosd
2049
        rep stosd
2050
        mov     eax, [ebp+NTFS.cur_subnode_size]
2050
        mov     eax, [ebp+NTFS.cur_subnode_size]
2051
        cmp     eax, [ebp+NTFS.cur_size]
2051
        cmp     eax, [ebp+NTFS.cur_size]
2052
        jnz     @f
2052
        jnz     @f
2053
        cmp     [ebp+NTFS.sectors_per_cluster], 1
2053
        cmp     [ebp+NTFS.sectors_per_cluster], 1
2054
        jz      @f
2054
        jz      @f
2055
        mov     al, 1
2055
        mov     al, 1
2056
@@:
2056
@@:
2057
        mov     [ebp+NTFS.fileDataSize], eax
2057
        mov     [ebp+NTFS.fileDataSize], eax
2058
        mov     edi, [ebp+NTFS.BitmapStart]
2058
        mov     edi, [ebp+NTFS.BitmapStart]
2059
        call    ntfsSpaceAlloc
2059
        call    ntfsSpaceAlloc
2060
        movi    eax, ERROR_DISK_FULL
2060
        movi    eax, ERROR_DISK_FULL
2061
        jc      ntfsErrorPop3
2061
        jc      ntfsErrorPop3
2062
; create $IndexAllocation
2062
; create $IndexAllocation
2063
        mov     edi, [ebp+NTFS.attr_offs]
2063
        mov     edi, [ebp+NTFS.attr_offs]
2064
        mov     byte [edi+attributeType], 0xA0
2064
        mov     byte [edi+attributeType], 0xA0
2065
        mov     byte [edi+nonResidentFlag], 1
2065
        mov     byte [edi+nonResidentFlag], 1
2066
        mov     byte [edi+nameLength], 4
2066
        mov     byte [edi+nameLength], 4
2067
        mov     byte [edi+nameOffset], 40h
2067
        mov     byte [edi+nameOffset], 40h
2068
        mov     byte [edi+dataRunsOffset], 48h
2068
        mov     byte [edi+dataRunsOffset], 48h
2069
        mov     byte [edi+sizeWithHeader], 50h
2069
        mov     byte [edi+sizeWithHeader], 50h
2070
        mov     eax, [ebp+NTFS.fileDataSize]
2070
        mov     eax, [ebp+NTFS.fileDataSize]
2071
        dec     eax
2071
        dec     eax
2072
        mov     [edi+lastVCN], eax
2072
        mov     [edi+lastVCN], eax
2073
        inc     eax
2073
        inc     eax
2074
        mul     [ebp+NTFS.sectors_per_cluster]
2074
        mul     [ebp+NTFS.sectors_per_cluster]
2075
        shl     eax, 9
2075
        shl     eax, 9
2076
        mov     [edi+attributeAllocatedSize], eax
2076
        mov     [edi+attributeAllocatedSize], eax
2077
        mov     [edi+attributeRealSize], eax
2077
        mov     [edi+attributeRealSize], eax
2078
        mov     [edi+initialDataSize], eax
2078
        mov     [edi+initialDataSize], eax
2079
        mov     dword[edi+40h], 490024h     ; unicode $I30
2079
        mov     dword[edi+40h], 490024h     ; unicode $I30
2080
        mov     dword[edi+40h+4], 300033h
2080
        mov     dword[edi+40h+4], 300033h
2081
        push    edi
2081
        push    edi
2082
        mov     esi, edi
2082
        mov     esi, edi
2083
        add     edi, 48h
2083
        add     edi, 48h
2084
        call    createMcbEntry
2084
        call    createMcbEntry
2085
        mov     esi, [ebp+NTFS.frs_buffer]
2085
        mov     esi, [ebp+NTFS.frs_buffer]
2086
        pop     edi
2086
        pop     edi
2087
        mov     al, [esi+newAttributeID]
2087
        mov     al, [esi+newAttributeID]
2088
        mov     [edi+attributeID], al
2088
        mov     [edi+attributeID], al
2089
        add     edi, 50h
2089
        add     edi, 50h
2090
        inc     eax
2090
        inc     eax
2091
; create $Bitmap
2091
; create $Bitmap
2092
        mov     [edi+attributeID], al
2092
        mov     [edi+attributeID], al
2093
        inc     eax
2093
        inc     eax
2094
        mov     [esi+newAttributeID], al
2094
        mov     [esi+newAttributeID], al
2095
        mov     byte [edi+attributeType], 0xB0
2095
        mov     byte [edi+attributeType], 0xB0
2096
        mov     byte [edi+nameLength], 4
2096
        mov     byte [edi+nameLength], 4
2097
        mov     byte [edi+nameOffset], 18h
2097
        mov     byte [edi+nameOffset], 18h
2098
        mov     byte [edi+attributeOffset], 20h
2098
        mov     byte [edi+attributeOffset], 20h
2099
        mov     byte [edi+sizeWithoutHeader], 8
2099
        mov     byte [edi+sizeWithoutHeader], 8
2100
        mov     byte [edi+sizeWithHeader], 28h
2100
        mov     byte [edi+sizeWithHeader], 28h
2101
        mov     dword[edi+18h], 490024h     ; unicode $I30
2101
        mov     dword[edi+18h], 490024h     ; unicode $I30
2102
        mov     dword[edi+18h+4], 300033h
2102
        mov     dword[edi+18h+4], 300033h
2103
        mov     byte [edi+20h], 1
2103
        mov     byte [edi+20h], 1
2104
        mov     dword[edi+28h], -1
2104
        mov     dword[edi+28h], -1
2105
        add     edi, 30h
2105
        add     edi, 30h
2106
        sub     edi, esi
2106
        sub     edi, esi
2107
        mov     [esi+recordRealSize], edi
2107
        mov     [esi+recordRealSize], edi
2108
        mov     eax, [ebp+NTFS.fileDataStart]
2108
        mov     eax, [ebp+NTFS.fileDataStart]
2109
        mul     [ebp+NTFS.sectors_per_cluster]
2109
        mul     [ebp+NTFS.sectors_per_cluster]
2110
        mov     edx, eax
2110
        mov     edx, eax
2111
        jmp     @f
2111
        jmp     @f
2112
 
2112
 
2113
.refresh:
2113
.refresh:
2114
        mov     [ebp+NTFS.cur_size], 0
2114
        mov     [ebp+NTFS.cur_size], 0
2115
        call    ntfs_read_attr.continue
2115
        call    ntfs_read_attr.continue
2116
        movi    eax, ERROR_FS_FAIL
2116
        movi    eax, ERROR_FS_FAIL
2117
        jc      ntfsErrorPop3
2117
        jc      ntfsErrorPop3
2118
        mov     edx, [ebp+NTFS.LastRead]
2118
        mov     edx, [ebp+NTFS.LastRead]
2119
@@:
2119
@@:
2120
        mov     ebx, [ebp+NTFS.cur_index_buf]
2120
        mov     ebx, [ebp+NTFS.cur_index_buf]
2121
        call    writeRecord
2121
        call    writeRecord
2122
        mov     ebx, [ebp+NTFS.frs_buffer]
2122
        mov     ebx, [ebp+NTFS.frs_buffer]
2123
        mov     edx, [ebp+NTFS.rootLastRead]
2123
        mov     edx, [ebp+NTFS.rootLastRead]
2124
        call    writeRecord
2124
        call    writeRecord
2125
        mov     esi, [esp+4]
2125
        mov     esi, [esp+4]
2126
        call    ntfs_find_lfn.doit2
2126
        call    ntfs_find_lfn.doit2
2127
        test    eax, eax
2127
        test    eax, eax
2128
        jz      .errorPop3
2128
        jz      .errorPop3
2129
        mov     edi, [ebp+NTFS.cur_index_buf]
2129
        mov     edi, [ebp+NTFS.cur_index_buf]
2130
        mov     edx, [esp]
2130
        mov     edx, [esp]
2131
.indexRecord:
2131
.indexRecord:
2132
        add     edi, recordNode
2132
        add     edi, recordNode
2133
        add     edx, [edi+nodeRealSize]
2133
        add     edx, [edi+nodeRealSize]
2134
        cmp     [edi+nodeAllocatedSize], edx
2134
        cmp     [edi+nodeAllocatedSize], edx
2135
        jc      .arborizeTree
2135
        jc      .arborizeTree
2136
        mov     [edi+nodeRealSize], edx
2136
        mov     [edi+nodeRealSize], edx
2137
        jmp     .common
2137
        jmp     .common
2138
 
2138
 
2139
.errorPop3:
2139
.errorPop3:
2140
        add     esp, 12
2140
        add     esp, 12
2141
        jmp     ntfsUnsupported
2141
        jmp     ntfsUnsupported
2142
 
2142
 
2143
.ntfsNodeAlloc:
2143
.ntfsNodeAlloc:
2144
; in: [ebp+NTFS.attr_offs] -> $IndexAllocation
2144
; in: [ebp+NTFS.attr_offs] -> $IndexAllocation
2145
;   out:
2145
;   out:
2146
; [ebp+NTFS.newRecord] = node VCN
2146
; [ebp+NTFS.newRecord] = node VCN
2147
; [ebp+NTFS.cur_offs]
2147
; [ebp+NTFS.cur_offs]
2148
; CF=1 -> eax = error code
2148
; CF=1 -> eax = error code
2149
        mov     esi, [ebp+NTFS.attr_offs]
2149
        mov     esi, [ebp+NTFS.attr_offs]
2150
        add     esi, [esi+sizeWithHeader]
2150
        add     esi, [esi+sizeWithHeader]
2151
        cmp     byte [esi], 0xB0
2151
        cmp     byte [esi], 0xB0
2152
        jnz     .ret
2152
        jnz     .ret
2153
        movzx   ecx, word [esi+sizeWithoutHeader]
2153
        movzx   ecx, word [esi+sizeWithoutHeader]
2154
        shr     ecx, 2
2154
        shr     ecx, 2
2155
        movzx   edi, byte [esi+attributeOffset]
2155
        movzx   edi, byte [esi+attributeOffset]
2156
        add     edi, esi
2156
        add     edi, esi
2157
        mov     edx, edi
2157
        mov     edx, edi
2158
        or      eax, -1
2158
        or      eax, -1
2159
        repz scasd
2159
        repz scasd
2160
        jnz     @f
2160
        jnz     @f
2161
        cmp     [edi], eax
2161
        cmp     [edi], eax
2162
        jnz     .ret
2162
        jnz     .ret
2163
; extend folder $Bitmap
2163
; extend folder $Bitmap
2164
        add     word [esi+sizeWithHeader], 8
2164
        add     word [esi+sizeWithHeader], 8
2165
        add     word [esi+sizeWithoutHeader], 8
2165
        add     word [esi+sizeWithoutHeader], 8
2166
        mov     esi, [ebp+NTFS.frs_buffer]
2166
        mov     esi, [ebp+NTFS.frs_buffer]
2167
        mov     eax, [esi+recordRealSize]
2167
        mov     eax, [esi+recordRealSize]
2168
        add     eax, 8
2168
        add     eax, 8
2169
        cmp     [esi+recordAllocatedSize], eax
2169
        cmp     [esi+recordAllocatedSize], eax
2170
        jc      .ret
2170
        jc      .ret
2171
        mov     [esi+recordRealSize], eax
2171
        mov     [esi+recordRealSize], eax
2172
        xor     eax, eax
2172
        xor     eax, eax
2173
        stosd
2173
        stosd
2174
        mov     [edi], eax
2174
        mov     [edi], eax
2175
        mov     [edi+8], eax
2175
        mov     [edi+8], eax
2176
        dec     eax
2176
        dec     eax
2177
        mov     [edi+4], eax
2177
        mov     [edi+4], eax
2178
@@:
2178
@@:
2179
        sub     edi, 4
2179
        sub     edi, 4
2180
        mov     eax, [edi]
2180
        mov     eax, [edi]
2181
        not     eax
2181
        not     eax
2182
        bsf     eax, eax
2182
        bsf     eax, eax
2183
        bts     [edi], eax
2183
        bts     [edi], eax
2184
        sub     edi, edx
2184
        sub     edi, edx
2185
        shl     edi, 3
2185
        shl     edi, 3
2186
        add     eax, edi
2186
        add     eax, edi
2187
        mul     [ebp+NTFS.cur_subnode_size]
2187
        mul     [ebp+NTFS.cur_subnode_size]
2188
        mov     [ebp+NTFS.newRecord], eax
2188
        mov     [ebp+NTFS.newRecord], eax
2189
        mov     ecx, [ebp+NTFS.cur_size]
2189
        mov     ecx, [ebp+NTFS.cur_size]
2190
        cmp     ecx, [ebp+NTFS.cur_subnode_size]
2190
        cmp     ecx, [ebp+NTFS.cur_subnode_size]
2191
        jz      @f
2191
        jz      @f
2192
        mul     [ebp+NTFS.sectors_per_cluster]
2192
        mul     [ebp+NTFS.sectors_per_cluster]
2193
@@:
2193
@@:
2194
        mov     [ebp+NTFS.cur_offs], eax
2194
        mov     [ebp+NTFS.cur_offs], eax
2195
        add     eax, ecx
2195
        add     eax, ecx
2196
        shl     eax, 9
2196
        shl     eax, 9
2197
        mov     esi, [ebp+NTFS.attr_offs]
2197
        mov     esi, [ebp+NTFS.attr_offs]
2198
        cmp     [esi+attributeAllocatedSize], eax
2198
        cmp     [esi+attributeAllocatedSize], eax
2199
        jnc     @f
2199
        jnc     @f
2200
        xor     edx, edx
2200
        xor     edx, edx
2201
        jmp     resizeAttribute
2201
        jmp     resizeAttribute
2202
 
2202
 
2203
.ret:
2203
.ret:
2204
        movi    eax, ERROR_UNSUPPORTED_FS
2204
        movi    eax, ERROR_UNSUPPORTED_FS
2205
        stc
2205
        stc
2206
@@:
2206
@@:
2207
        ret
2207
        ret
2208
 
2208
 
2209
.arborizeTree:      ; find median index
2209
.arborizeTree:      ; find median index
2210
        mov     ecx, [edi+nodeRealSize]
2210
        mov     ecx, [edi+nodeRealSize]
2211
        sub     ecx, [edi+indexOffset]
2211
        sub     ecx, [edi+indexOffset]
2212
        shr     ecx, 1
2212
        shr     ecx, 1
2213
        add     edi, [edi+indexOffset]
2213
        add     edi, [edi+indexOffset]
2214
        xor     eax, eax
2214
        xor     eax, eax
2215
@@:
2215
@@:
2216
        add     edi, eax
2216
        add     edi, eax
2217
        mov     ax, [edi+indexAllocatedSize]
2217
        mov     ax, [edi+indexAllocatedSize]
2218
        sub     ecx, eax
2218
        sub     ecx, eax
2219
        jnc     @b
2219
        jnc     @b
2220
        add     eax, 8
2220
        add     eax, 8
2221
        mov     esi, [ebp+NTFS.secondIndexBuffer]
2221
        mov     esi, [ebp+NTFS.secondIndexBuffer]
2222
        cmp     dword [esi], 'INDX'
2222
        cmp     dword [esi], 'INDX'
2223
        jz      @f
2223
        jz      @f
2224
; move index to the root node
2224
; move index to the root node
2225
        mov     esi, [ebp+NTFS.frs_buffer]
2225
        mov     esi, [ebp+NTFS.frs_buffer]
2226
        mov     ecx, eax
2226
        mov     ecx, eax
2227
        add     ecx, 8
2227
        add     ecx, 8
2228
        add     ecx, [esi+recordRealSize]
2228
        add     ecx, [esi+recordRealSize]
2229
        cmp     [esi+recordAllocatedSize], ecx
2229
        cmp     [esi+recordAllocatedSize], ecx
2230
        jc      .growTree
2230
        jc      .growTree
2231
        push    edi eax
2231
        push    edi eax
2232
        call    .ntfsNodeAlloc
2232
        call    .ntfsNodeAlloc
2233
        jc      ntfsErrorPop5
2233
        jc      ntfsErrorPop5
2234
        pop     eax
2234
        pop     eax
2235
        mov     edi, [ebp+NTFS.indexRoot]
2235
        mov     edi, [ebp+NTFS.indexRoot]
2236
        add     [ebp+NTFS.attr_offs], eax
2236
        add     [ebp+NTFS.attr_offs], eax
2237
        add     [edi+sizeWithHeader], eax
2237
        add     [edi+sizeWithHeader], eax
2238
        add     [edi+sizeWithoutHeader], eax
2238
        add     [edi+sizeWithoutHeader], eax
2239
        movzx   ecx, byte [edi+attributeOffset]
2239
        movzx   ecx, byte [edi+attributeOffset]
2240
        add     ecx, edi
2240
        add     ecx, edi
2241
        add     [ecx+rootNode+nodeRealSize], eax
2241
        add     [ecx+rootNode+nodeRealSize], eax
2242
        add     [ecx+rootNode+nodeAllocatedSize], eax
2242
        add     [ecx+rootNode+nodeAllocatedSize], eax
2243
        add     ecx, [ebp+NTFS.indexPointer]
2243
        add     ecx, [ebp+NTFS.indexPointer]
2244
        sub     ecx, [ebp+NTFS.secondIndexBuffer]
2244
        sub     ecx, [ebp+NTFS.secondIndexBuffer]
2245
        mov     esi, [ebp+NTFS.frs_buffer]
2245
        mov     esi, [ebp+NTFS.frs_buffer]
2246
        add     [esi+recordRealSize], eax
2246
        add     [esi+recordRealSize], eax
2247
        add     esi, [esi+recordRealSize]
2247
        add     esi, [esi+recordRealSize]
2248
        mov     edi, esi
2248
        mov     edi, esi
2249
        sub     esi, eax
2249
        sub     esi, eax
2250
        neg     ecx
2250
        neg     ecx
2251
        add     ecx, esi
2251
        add     ecx, esi
2252
        shr     ecx, 2
2252
        shr     ecx, 2
2253
        sub     esi, 4
2253
        sub     esi, 4
2254
        sub     edi, 4
2254
        sub     edi, 4
2255
        std
2255
        std
2256
        rep movsd   ; make space
2256
        rep movsd   ; make space
2257
        mov     [edi], ecx
2257
        mov     [edi], ecx
2258
        mov     edi, esi
2258
        mov     edi, esi
2259
        add     edi, 4
2259
        add     edi, 4
2260
        mov     esi, [esp]
2260
        mov     esi, [esp]
2261
        add     word [esi+indexAllocatedSize], 8
2261
        add     word [esi+indexAllocatedSize], 8
2262
        mov     byte [esi+indexFlags], 1
2262
        mov     byte [esi+indexFlags], 1
2263
        mov     ecx, eax
2263
        mov     ecx, eax
2264
        sub     ecx, 8
2264
        sub     ecx, 8
2265
        shr     ecx, 2
2265
        shr     ecx, 2
2266
        cld
2266
        cld
2267
        rep movsd   ; insert index
2267
        rep movsd   ; insert index
2268
        mov     eax, [ebp+NTFS.newRecord]
2268
        mov     eax, [ebp+NTFS.newRecord]
2269
        stosd
2269
        stosd
2270
        jmp     .splitNode
2270
        jmp     .splitNode
2271
 
2271
 
2272
.growBranch:    ; move node and replace it with empty one
2272
.growBranch:    ; move node and replace it with empty one
2273
        mov     esi, [ebp+NTFS.cur_index_buf]
2273
        mov     esi, [ebp+NTFS.cur_index_buf]
2274
        mov     edi, [ebp+NTFS.secondIndexBuffer]
2274
        mov     edi, [ebp+NTFS.secondIndexBuffer]
2275
        mov     eax, [esi+recordVCN]
2275
        mov     eax, [esi+recordVCN]
2276
        mov     [edi+recordVCN], eax
2276
        mov     [edi+recordVCN], eax
2277
        add     edi, recordNode
2277
        add     edi, recordNode
2278
        mov     eax, [edi+indexOffset]
2278
        mov     eax, [edi+indexOffset]
2279
        add     eax, 18h
2279
        add     eax, 18h
2280
        mov     [edi+nodeRealSize], eax
2280
        mov     [edi+nodeRealSize], eax
2281
        add     edi, [edi+indexOffset]
2281
        add     edi, [edi+indexOffset]
2282
        mov     ecx, 6
2282
        mov     ecx, 6
2283
        xor     eax, eax
2283
        xor     eax, eax
2284
        mov     [ebp+NTFS.indexPointer], edi
2284
        mov     [ebp+NTFS.indexPointer], edi
2285
        push    edi
2285
        push    edi
2286
        rep stosd
2286
        rep stosd
2287
        pop     edi
2287
        pop     edi
2288
        mov     eax, [ebp+NTFS.newRecord]
2288
        mov     eax, [ebp+NTFS.newRecord]
2289
        mov     byte [edi+indexAllocatedSize], 18h
2289
        mov     byte [edi+indexAllocatedSize], 18h
2290
        mov     byte [edi+indexFlags], 3
2290
        mov     byte [edi+indexFlags], 3
2291
        mov     [edi+16], eax
2291
        mov     [edi+16], eax
2292
        mov     [esi+recordVCN], eax
2292
        mov     [esi+recordVCN], eax
2293
        mov     eax, [ebp+NTFS.LastRead]
2293
        mov     eax, [ebp+NTFS.LastRead]
2294
        mov     [ebp+NTFS.nodeLastRead], eax
2294
        mov     [ebp+NTFS.nodeLastRead], eax
2295
        push    [ebp+NTFS.cur_size]
2295
        push    [ebp+NTFS.cur_size]
2296
        mov     [ebp+NTFS.cur_size], 0
2296
        mov     [ebp+NTFS.cur_size], 0
2297
        call    ntfs_read_attr.continue
2297
        call    ntfs_read_attr.continue
2298
        pop     [ebp+NTFS.cur_size]
2298
        pop     [ebp+NTFS.cur_size]
2299
        movi    eax, ERROR_FS_FAIL
2299
        movi    eax, ERROR_FS_FAIL
2300
        jc      ntfsErrorPop5
2300
        jc      ntfsErrorPop5
2301
        pop     eax edi
2301
        pop     eax edi
2302
@@:         ; move index to the branch node
2302
@@:         ; move index to the branch node
2303
        push    edi eax
2303
        push    edi eax
2304
        call    .ntfsNodeAlloc
2304
        call    .ntfsNodeAlloc
2305
        jc      ntfsErrorPop5
2305
        jc      ntfsErrorPop5
2306
        mov     eax, [esp]
2306
        mov     eax, [esp]
2307
        mov     esi, [ebp+NTFS.secondIndexBuffer]
2307
        mov     esi, [ebp+NTFS.secondIndexBuffer]
2308
        add     esi, recordNode
2308
        add     esi, recordNode
2309
        mov     ecx, [esi+nodeRealSize]
2309
        mov     ecx, [esi+nodeRealSize]
2310
        add     eax, ecx
2310
        add     eax, ecx
2311
        cmp     [esi+nodeAllocatedSize], eax
2311
        cmp     [esi+nodeAllocatedSize], eax
2312
        jc      .growBranch
2312
        jc      .growBranch
2313
        mov     [esi+nodeRealSize], eax
2313
        mov     [esi+nodeRealSize], eax
2314
        lea     edi, [esi+eax-4]
2314
        lea     edi, [esi+eax-4]
2315
        add     esi, ecx
2315
        add     esi, ecx
2316
        mov     ecx, esi
2316
        mov     ecx, esi
2317
        sub     ecx, [ebp+NTFS.indexPointer]
2317
        sub     ecx, [ebp+NTFS.indexPointer]
2318
        shr     ecx, 2
2318
        shr     ecx, 2
2319
        sub     esi, 4
2319
        sub     esi, 4
2320
        std
2320
        std
2321
        rep movsd   ; make space
2321
        rep movsd   ; make space
2322
        mov     [edi], ecx
2322
        mov     [edi], ecx
2323
        pop     ecx
2323
        pop     ecx
2324
        sub     ecx, 8
2324
        sub     ecx, 8
2325
        shr     ecx, 2
2325
        shr     ecx, 2
2326
        mov     edi, esi
2326
        mov     edi, esi
2327
        add     edi, 4
2327
        add     edi, 4
2328
        mov     esi, [esp]
2328
        mov     esi, [esp]
2329
        add     word [esi+indexAllocatedSize], 8
2329
        add     word [esi+indexAllocatedSize], 8
2330
        mov     byte [esi+indexFlags], 1
2330
        mov     byte [esi+indexFlags], 1
2331
        cld
2331
        cld
2332
        rep movsd   ; insert index
2332
        rep movsd   ; insert index
2333
        mov     eax, [ebp+NTFS.newRecord]
2333
        mov     eax, [ebp+NTFS.newRecord]
2334
        stosd
2334
        stosd
2335
        mov     ebx, [ebp+NTFS.secondIndexBuffer]
2335
        mov     ebx, [ebp+NTFS.secondIndexBuffer]
2336
        mov     edx, [ebp+NTFS.nodeLastRead]
2336
        mov     edx, [ebp+NTFS.nodeLastRead]
2337
        push    esi
2337
        push    esi
2338
        call    writeRecord
2338
        call    writeRecord
2339
        pop     esi
2339
        pop     esi
2340
.splitNode:
2340
.splitNode:
2341
        mov     edi, [ebp+NTFS.cur_index_buf]
2341
        mov     edi, [ebp+NTFS.cur_index_buf]
2342
        mov     eax, edi
2342
        mov     eax, edi
2343
        add     eax, recordNode
2343
        add     eax, recordNode
2344
        add     eax, [edi+recordNode+nodeRealSize]
2344
        add     eax, [edi+recordNode+nodeRealSize]
2345
        sub     eax, esi
2345
        sub     eax, esi
2346
        push    eax
2346
        push    eax
2347
        mov     ecx, [edi+recordNode+indexOffset]
2347
        mov     ecx, [edi+recordNode+indexOffset]
2348
        add     eax, ecx
2348
        add     eax, ecx
2349
        add     ecx, recordNode
2349
        add     ecx, recordNode
2350
        shr     ecx, 2
2350
        shr     ecx, 2
2351
        push    esi
2351
        push    esi
2352
        mov     esi, edi
2352
        mov     esi, edi
2353
        mov     edi, [ebp+NTFS.secondIndexBuffer]
2353
        mov     edi, [ebp+NTFS.secondIndexBuffer]
2354
        rep movsd
2354
        rep movsd
2355
        pop     esi
2355
        pop     esi
2356
        pop     ecx
2356
        pop     ecx
2357
        shr     ecx, 2
2357
        shr     ecx, 2
2358
        rep movsd
2358
        rep movsd
2359
        mov     edi, [ebp+NTFS.secondIndexBuffer]
2359
        mov     edi, [ebp+NTFS.secondIndexBuffer]
2360
        mov     [edi+recordNode+nodeRealSize], eax
2360
        mov     [edi+recordNode+nodeRealSize], eax
2361
        pop     edi
2361
        pop     edi
2362
        mov     cl, 4
2362
        mov     cl, 4
2363
        xor     eax, eax
2363
        xor     eax, eax
2364
        mov     esi, edi
2364
        mov     esi, edi
2365
        rep stosd
2365
        rep stosd
2366
        mov     byte [esi+indexAllocatedSize], 16
2366
        mov     byte [esi+indexAllocatedSize], 16
2367
        mov     byte [esi+indexFlags], 2
2367
        mov     byte [esi+indexFlags], 2
2368
        mov     esi, [ebp+NTFS.cur_index_buf]
2368
        mov     esi, [ebp+NTFS.cur_index_buf]
2369
        mov     eax, [ebp+NTFS.newRecord]
2369
        mov     eax, [ebp+NTFS.newRecord]
2370
        mov     [esi+recordVCN], eax
2370
        mov     [esi+recordVCN], eax
2371
        add     esi, recordNode
2371
        add     esi, recordNode
2372
        sub     edi, esi
2372
        sub     edi, esi
2373
        mov     [esi+nodeRealSize], edi
2373
        mov     [esi+nodeRealSize], edi
2374
        mov     ebx, [ebp+NTFS.secondIndexBuffer]
2374
        mov     ebx, [ebp+NTFS.secondIndexBuffer]
2375
        mov     edx, [ebp+NTFS.LastRead]
2375
        mov     edx, [ebp+NTFS.LastRead]
2376
        call    writeRecord
2376
        call    writeRecord
2377
        jmp     .refresh
2377
        jmp     .refresh
2378
 
2378
 
2379
.common:
2379
.common:
2380
        add     edi, edx
2380
        add     edi, edx
2381
        sub     edi, 4
2381
        sub     edi, 4
2382
        mov     esi, edi
2382
        mov     esi, edi
2383
        sub     esi, [esp]
2383
        sub     esi, [esp]
2384
        mov     ecx, esi
2384
        mov     ecx, esi
2385
        sub     ecx, eax    ; eax = pointer in the record
2385
        sub     ecx, eax    ; eax = pointer in the record
2386
        shr     ecx, 2
2386
        shr     ecx, 2
2387
        inc     ecx
2387
        inc     ecx
2388
        std
2388
        std
2389
        rep movsd           ; move forward, make space
2389
        rep movsd           ; move forward, make space
2390
        mov     ecx, [esp]
2390
        mov     ecx, [esp]
2391
        shr     ecx, 2
2391
        shr     ecx, 2
2392
        xor     eax, eax
2392
        xor     eax, eax
2393
        rep stosd
2393
        rep stosd
2394
        cld
2394
        cld
2395
        add     edi, 4
2395
        add     edi, 4
2396
        call    ntfsGetTime
2396
        call    ntfsGetTime
2397
        mov     [edi+fileCreated], eax
2397
        mov     [edi+fileCreated], eax
2398
        mov     [edi+fileCreated+4], edx
2398
        mov     [edi+fileCreated+4], edx
2399
        mov     [edi+fileModified], eax
2399
        mov     [edi+fileModified], eax
2400
        mov     [edi+fileModified+4], edx
2400
        mov     [edi+fileModified+4], edx
2401
        mov     [edi+recordModified], eax
2401
        mov     [edi+recordModified], eax
2402
        mov     [edi+recordModified+4], edx
2402
        mov     [edi+recordModified+4], edx
2403
        mov     [edi+fileAccessed], eax
2403
        mov     [edi+fileAccessed], eax
2404
        mov     [edi+fileAccessed+4], edx
2404
        mov     [edi+fileAccessed+4], edx
2405
        pop     ecx
2405
        pop     ecx
2406
        pop     esi
2406
        pop     esi
2407
        mov     [edi+indexAllocatedSize], cx    ; fill index with data
2407
        mov     [edi+indexAllocatedSize], cx    ; fill index with data
2408
        mov     eax, [esp]
2408
        mov     eax, [esp]
2409
        shl     eax, 1
2409
        shl     eax, 1
2410
        add     eax, 42h
2410
        add     eax, 42h
2411
        mov     [edi+indexRawSize], ax
2411
        mov     [edi+indexRawSize], ax
2412
        mov     eax, [ebp+NTFS.cur_iRecord]
2412
        mov     eax, [ebp+NTFS.cur_iRecord]
2413
        mov     [edi+directoryRecordReference], eax
2413
        mov     [edi+directoryRecordReference], eax
2414
        mov     eax, [ebp+NTFS.frs_buffer]
2414
        mov     eax, [ebp+NTFS.frs_buffer]
2415
        mov     eax, [eax+reuseCounter]
2415
        mov     eax, [eax+reuseCounter]
2416
        mov     [edi+directoryReferenceReuse], ax
2416
        mov     [edi+directoryReferenceReuse], ax
2417
        mov     eax, [ebp+NTFS.frs_size]
2417
        mov     eax, [ebp+NTFS.frs_size]
2418
        shr     eax, 8
2418
        shr     eax, 8
2419
        add     ecx, 30h+48h+8+18h+8
2419
        add     ecx, 30h+48h+8+18h+8
2420
        add     ecx, eax
2420
        add     ecx, eax
2421
        mov     eax, [ebp+NTFS.fileRealSize]
2421
        mov     eax, [ebp+NTFS.fileRealSize]
2422
        add     ecx, eax
2422
        add     ecx, eax
2423
        mov     [edi+fileRealSize], eax
2423
        mov     [edi+fileRealSize], eax
2424
        cmp     [ebp+NTFS.frs_size], ecx
2424
        cmp     [ebp+NTFS.frs_size], ecx
2425
        jc      @f
2425
        jc      @f
2426
        xor     eax, eax
2426
        xor     eax, eax
2427
@@:
2427
@@:
2428
        mov     ecx, [ebp+NTFS.sectors_per_cluster]
2428
        mov     ecx, [ebp+NTFS.sectors_per_cluster]
2429
        shl     ecx, 9
2429
        shl     ecx, 9
2430
        add     eax, ecx
2430
        add     eax, ecx
2431
        dec     eax
2431
        dec     eax
2432
        xor     edx, edx
2432
        xor     edx, edx
2433
        div     ecx
2433
        div     ecx
2434
        mov     [ebp+NTFS.fileDataSize], eax
2434
        mov     [ebp+NTFS.fileDataSize], eax
2435
        mul     ecx
2435
        mul     ecx
2436
        mov     [edi+fileAllocatedSize], eax
2436
        mov     [edi+fileAllocatedSize], eax
2437
        pop     ecx
2437
        pop     ecx
2438
        mov     [ebp+NTFS.indexPointer], edi
2438
        mov     [ebp+NTFS.indexPointer], edi
2439
        mov     [edi+fileNameLength], cl
2439
        mov     [edi+fileNameLength], cl
2440
        add     edi, fileName
2440
        add     edi, fileName
2441
@@:         ; record filename
2441
@@:         ; record filename
2442
        call    utf8to16
2442
        call    utf8to16
2443
        stosw
2443
        stosw
2444
        loop    @b
2444
        loop    @b
2445
        mov     eax, [ebp+NTFS.LastRead]
2445
        mov     eax, [ebp+NTFS.LastRead]
2446
        mov     [ebp+NTFS.nodeLastRead], eax
2446
        mov     [ebp+NTFS.nodeLastRead], eax
2447
        cmp     [ebp+NTFS.bFolder], 0
2447
        cmp     [ebp+NTFS.bFolder], 0
2448
        jz      @f
2448
        jz      @f
2449
        mov     edi, [ebp+NTFS.indexPointer]
2449
        mov     edi, [ebp+NTFS.indexPointer]
2450
        bts     dword [edi+fileFlags], 28
2450
        bts     dword [edi+fileFlags], 28
2451
        jmp     .mftBitmap
2451
        jmp     .mftBitmap
2452
 
2452
 
2453
@@: ; 3. File data
2453
@@: ; 3. File data
2454
        cmp     [ebp+NTFS.fileDataSize], 0
2454
        cmp     [ebp+NTFS.fileDataSize], 0
2455
        jz      .mftBitmap
2455
        jz      .mftBitmap
2456
        mov     edi, [ebp+NTFS.BitmapStart]
2456
        mov     edi, [ebp+NTFS.BitmapStart]
2457
        call    ntfsSpaceAlloc
2457
        call    ntfsSpaceAlloc
2458
        jc      ntfsDiskFull
2458
        jc      ntfsDiskFull
2459
        mov     eax, [ebp+NTFS.fileDataStart]
2459
        mov     eax, [ebp+NTFS.fileDataStart]
2460
        mul     [ebp+NTFS.sectors_per_cluster]
2460
        mul     [ebp+NTFS.sectors_per_cluster]
2461
        mov     ecx, [ebp+NTFS.fileRealSize]
2461
        mov     ecx, [ebp+NTFS.fileRealSize]
2462
        add     ecx, 511
2462
        add     ecx, 511
2463
        shr     ecx, 9
2463
        shr     ecx, 9
2464
        mov     ebx, [ebp+NTFS.fileDataBuffer]
2464
        mov     ebx, [ebp+NTFS.fileDataBuffer]
2465
        call    fs_write64_app
2465
        call    fs_write64_app
2466
        test    eax, eax
2466
        test    eax, eax
2467
        jnz     ntfsDevice
2467
        jnz     ntfsDevice
2468
    ; 4. MFT record
2468
    ; 4. MFT record
2469
.mftBitmap: ; search for free record
2469
.mftBitmap: ; search for free record
2470
        mov     edi, [ebp+NTFS.mftBitmapBuffer]
2470
        mov     edi, [ebp+NTFS.mftBitmapBuffer]
2471
        mov     ecx, [ebp+NTFS.mftBitmapSize]
2471
        mov     ecx, [ebp+NTFS.mftBitmapSize]
2472
        mov     al, -1
2472
        mov     al, -1
2473
        add     edi, 3
2473
        add     edi, 3
2474
        sub     ecx, 3
2474
        sub     ecx, 3
2475
        repz scasb
2475
        repz scasb
2476
        dec     edi
2476
        dec     edi
2477
        movzx   eax, byte [edi]
2477
        movzx   eax, byte [edi]
2478
        not     al
2478
        not     al
2479
        bsf     ecx, eax
2479
        bsf     ecx, eax
2480
        jz      .extendBitmapMFT    ; no free records
2480
        jz      .extendBitmapMFT    ; no free records
2481
        bts     [edi], ecx
2481
        bts     [edi], ecx
2482
; get record location
2482
; get record location
2483
        sub     edi, [ebp+NTFS.mftBitmapBuffer]
2483
        sub     edi, [ebp+NTFS.mftBitmapBuffer]
2484
        shl     edi, 3
2484
        shl     edi, 3
2485
        add     edi, ecx
2485
        add     edi, ecx
2486
        mov     [ebp+NTFS.newRecord], edi
2486
        mov     [ebp+NTFS.newRecord], edi
2487
        mov     eax, [ebp+NTFS.frs_size]
2487
        mov     eax, [ebp+NTFS.frs_size]
2488
        shr     eax, 9
2488
        shr     eax, 9
2489
        mul     edi
2489
        mul     edi
2490
        mov     [ebp+NTFS.cur_iRecord], 0
2490
        mov     [ebp+NTFS.cur_iRecord], 0
2491
        mov     [ebp+NTFS.cur_attr], 0x80
2491
        mov     [ebp+NTFS.cur_attr], 0x80
2492
        mov     [ebp+NTFS.cur_offs], eax
2492
        mov     [ebp+NTFS.cur_offs], eax
2493
        push    eax
2493
        push    eax
2494
        mov     [ebp+NTFS.cur_size], 0
2494
        mov     [ebp+NTFS.cur_size], 0
2495
        mov     eax, [ebp+NTFS.frs_buffer]
2495
        mov     eax, [ebp+NTFS.frs_buffer]
2496
        mov     [ebp+NTFS.cur_buf], eax
2496
        mov     [ebp+NTFS.cur_buf], eax
2497
        call    ntfs_read_attr
2497
        call    ntfs_read_attr
2498
        pop     eax
2498
        pop     eax
2499
        jc      ntfsFail
2499
        jc      ntfsFail
2500
        cmp     eax, [ebp+NTFS.mftSize]
2500
        cmp     eax, [ebp+NTFS.mftSize]
2501
        jnc     .extendMFT
2501
        jnc     .extendMFT
2502
        jmp     .mftRecord
2502
        jmp     .mftRecord
2503
 
2503
 
2504
.extendBitmapMFT:
2504
.extendBitmapMFT:
2505
        mov     eax, [ebp+NTFS.sectors_per_cluster]
2505
        mov     eax, [ebp+NTFS.sectors_per_cluster]
2506
        mov     [ebp+NTFS.cur_offs], eax
2506
        mov     [ebp+NTFS.cur_offs], eax
2507
        shl     eax, 9
2507
        shl     eax, 9
2508
        cmp     [ebp+NTFS.mftBitmapSize], eax
2508
        cmp     [ebp+NTFS.mftBitmapSize], eax
2509
        jnc     ntfsUnsupported
2509
        jnc     ntfsUnsupported
2510
        mov     [ebp+NTFS.cur_iRecord], 0
2510
        mov     [ebp+NTFS.cur_iRecord], 0
2511
        mov     [ebp+NTFS.cur_attr], 0xB0
2511
        mov     [ebp+NTFS.cur_attr], 0xB0
2512
        mov     [ebp+NTFS.cur_size], 0
2512
        mov     [ebp+NTFS.cur_size], 0
2513
        call    ntfs_read_attr
2513
        call    ntfs_read_attr
2514
        jc      ntfsFail
2514
        jc      ntfsFail
2515
        mov     eax, [ebp+NTFS.mft_cluster]
2515
        mov     eax, [ebp+NTFS.mft_cluster]
2516
        mul     [ebp+NTFS.sectors_per_cluster]
2516
        mul     [ebp+NTFS.sectors_per_cluster]
2517
        cmp     eax, [ebp+NTFS.LastRead]
2517
        cmp     eax, [ebp+NTFS.LastRead]
2518
        jnz     ntfsUnsupported     ; auxiliary record
2518
        jnz     ntfsUnsupported     ; auxiliary record
2519
        mov     edi, [ebp+NTFS.mftBitmapBuffer]
2519
        mov     edi, [ebp+NTFS.mftBitmapBuffer]
2520
        mov     ecx, [ebp+NTFS.mftBitmapSize]
2520
        mov     ecx, [ebp+NTFS.mftBitmapSize]
2521
        add     edi, ecx
2521
        add     edi, ecx
2522
        mov     eax, ecx
2522
        mov     eax, ecx
2523
        mov     edx, [ebp+NTFS.attr_offs]
2523
        mov     edx, [ebp+NTFS.attr_offs]
2524
        add     ecx, 8
2524
        add     ecx, 8
2525
        mov     [edx+attributeRealSize], ecx
2525
        mov     [edx+attributeRealSize], ecx
2526
        mov     [edx+initialDataSize], ecx
2526
        mov     [edx+initialDataSize], ecx
2527
        shl     eax, 3
2527
        shl     eax, 3
2528
        mov     [ebp+NTFS.newRecord], eax
2528
        mov     [ebp+NTFS.newRecord], eax
2529
        mov     dword [edi], 1
2529
        mov     dword [edi], 1
2530
        mov     dword [edi+4], 0
2530
        mov     dword [edi+4], 0
2531
        mov     [ebp+NTFS.cur_attr], 0x80
2531
        mov     [ebp+NTFS.cur_attr], 0x80
2532
        mov     [ebp+NTFS.cur_offs], 0
2532
        mov     [ebp+NTFS.cur_offs], 0
2533
        call    ntfs_read_attr.newAttribute
2533
        call    ntfs_read_attr.newAttribute
2534
        jc      ntfsFail
2534
        jc      ntfsFail
2535
        mov     [ebp+NTFS.mftBitmapSize], ecx
2535
        mov     [ebp+NTFS.mftBitmapSize], ecx
2536
.extendMFT:
2536
.extendMFT:
2537
        mov     eax, [ebp+NTFS.mft_cluster]
2537
        mov     eax, [ebp+NTFS.mft_cluster]
2538
        mul     [ebp+NTFS.sectors_per_cluster]
2538
        mul     [ebp+NTFS.sectors_per_cluster]
2539
        cmp     eax, [ebp+NTFS.LastRead]
2539
        cmp     eax, [ebp+NTFS.LastRead]
2540
        jnz     ntfsUnsupported     ; auxiliary record
2540
        jnz     ntfsUnsupported     ; auxiliary record
2541
        mov     ecx, [ebp+NTFS.attr_offs]
2541
        mov     ecx, [ebp+NTFS.attr_offs]
2542
        mov     eax, [ecx+attributeRealSize]
2542
        mov     eax, [ecx+attributeRealSize]
2543
        mov     edx, [ecx+attributeRealSize+4]
2543
        mov     edx, [ecx+attributeRealSize+4]
2544
        xor     ax, ax
2544
        xor     ax, ax
2545
        add     eax, 10000h
2545
        add     eax, 10000h
2546
        adc     edx, 0
2546
        adc     edx, 0
2547
        push    [ebp+NTFS.fileDataStart]
2547
        push    [ebp+NTFS.fileDataStart]
2548
        push    [ebp+NTFS.fileDataSize]
2548
        push    [ebp+NTFS.fileDataSize]
2549
        call    resizeAttribute
2549
        call    resizeAttribute
2550
        jc      ntfsErrorPop2
2550
        jc      ntfsErrorPop2
2551
        mov     ebx, [ebp+NTFS.frs_buffer]
2551
        mov     ebx, [ebp+NTFS.frs_buffer]
2552
        mov     edx, [ebp+NTFS.LastRead]
2552
        mov     edx, [ebp+NTFS.LastRead]
2553
        call    writeRecord     ; $MFT
2553
        call    writeRecord     ; $MFT
2554
        mov     eax, [ebp+NTFS.mftmirr_cluster]
2554
        mov     eax, [ebp+NTFS.mftmirr_cluster]
2555
        mul     [ebp+NTFS.sectors_per_cluster]
2555
        mul     [ebp+NTFS.sectors_per_cluster]
2556
        mov     ecx, [ebp+NTFS.frs_size]
2556
        mov     ecx, [ebp+NTFS.frs_size]
2557
        shr     ecx, 9
2557
        shr     ecx, 9
2558
        call    fs_write64_sys  ; $MFTMirr
2558
        call    fs_write64_sys  ; $MFTMirr
2559
; update $MFT retrieval information
2559
; update $MFT retrieval information
2560
        mov     edi, [ebp+NTFS.mft_retrieval_end]
2560
        mov     edi, [ebp+NTFS.mft_retrieval_end]
2561
        mov     eax, [edi-4]
2561
        mov     eax, [edi-4]
2562
        add     eax, [edi-8]
2562
        add     eax, [edi-8]
2563
        mov     edx, [ebp+NTFS.fileDataSize]
2563
        mov     edx, [ebp+NTFS.fileDataSize]
2564
        cmp     eax, [ebp+NTFS.fileDataStart]
2564
        cmp     eax, [ebp+NTFS.fileDataStart]
2565
        jnz     .newFragment
2565
        jnz     .newFragment
2566
        add     [edi-8], edx
2566
        add     [edi-8], edx
2567
        jmp     @f
2567
        jmp     @f
2568
.newFragment:
2568
.newFragment:
2569
        lea     eax, [ebp+NTFS.attrlist_buf]
2569
        lea     eax, [ebp+NTFS.attrlist_buf]
2570
        cmp     eax, edi
2570
        cmp     eax, edi
2571
        jz      @f
2571
        jz      @f
2572
        mov     [edi], edx
2572
        mov     [edi], edx
2573
        mov     eax, [ebp+NTFS.fileDataStart]
2573
        mov     eax, [ebp+NTFS.fileDataStart]
2574
        mov     [edi+4], eax
2574
        mov     [edi+4], eax
2575
        add     [ebp+NTFS.mft_retrieval_end], 8
2575
        add     [ebp+NTFS.mft_retrieval_end], 8
2576
@@:
2576
@@:
2577
        mov     eax, [ebp+NTFS.fileDataSize]
2577
        mov     eax, [ebp+NTFS.fileDataSize]
2578
        mul     [ebp+NTFS.sectors_per_cluster]
2578
        mul     [ebp+NTFS.sectors_per_cluster]
2579
        add     [ebp+NTFS.mftSize], eax
2579
        add     [ebp+NTFS.mftSize], eax
2580
        call    ntfsSpaceClean
2580
        call    ntfsSpaceClean
2581
        pop     [ebp+NTFS.fileDataSize]
2581
        pop     [ebp+NTFS.fileDataSize]
2582
        pop     [ebp+NTFS.fileDataStart]
2582
        pop     [ebp+NTFS.fileDataStart]
2583
.mftRecord:
2583
.mftRecord:
2584
        mov     ecx, [ebp+NTFS.frs_size]
2584
        mov     ecx, [ebp+NTFS.frs_size]
2585
        shr     ecx, 2
2585
        shr     ecx, 2
2586
        mov     edi, [ebp+NTFS.frs_buffer]
2586
        mov     edi, [ebp+NTFS.frs_buffer]
2587
        xor     eax, eax
2587
        xor     eax, eax
2588
        rep stosd
2588
        rep stosd
2589
        mov     esi, [ebp+NTFS.indexPointer]
2589
        mov     esi, [ebp+NTFS.indexPointer]
2590
        mov     eax, [ebp+NTFS.newRecord]
2590
        mov     eax, [ebp+NTFS.newRecord]
2591
        mov     [esi+fileRecordReference], eax
2591
        mov     [esi+fileRecordReference], eax
2592
        rdtsc
2592
        rdtsc
2593
        mov     [esi+fileReferenceReuse], ax
2593
        mov     [esi+fileReferenceReuse], ax
2594
        mov     edi, [ebp+NTFS.frs_buffer]
2594
        mov     edi, [ebp+NTFS.frs_buffer]
2595
; record header
2595
; record header
2596
        mov     [edi+reuseCounter], ax
2596
        mov     [edi+reuseCounter], ax
2597
        mov     [edi+2ah], ax
2597
        mov     [edi+2ah], ax
2598
        mov     eax, [ebp+NTFS.frs_size]
2598
        mov     eax, [ebp+NTFS.frs_size]
2599
        mov     [edi+recordAllocatedSize], eax
2599
        mov     [edi+recordAllocatedSize], eax
2600
        shr     eax, 9
2600
        shr     eax, 9
2601
        inc     eax
2601
        inc     eax
2602
        mov     [edi+updateSequenceSize], al
2602
        mov     [edi+updateSequenceSize], al
2603
        shl     eax, 1
2603
        shl     eax, 1
2604
        add     eax, 2ah+7
2604
        add     eax, 2ah+7
2605
        and     eax, not 7
2605
        and     eax, not 7
2606
        mov     dword[edi], 'FILE'
2606
        mov     dword[edi], 'FILE'
2607
        mov     byte [edi+updateSequenceOffset], 2ah
2607
        mov     byte [edi+updateSequenceOffset], 2ah
2608
        mov     byte [edi+hardLinkCounter], 1
2608
        mov     byte [edi+hardLinkCounter], 1
2609
        mov     byte [edi+newAttributeID], 3
2609
        mov     byte [edi+newAttributeID], 3
2610
        mov     [edi+attributeOffset], al
2610
        mov     [edi+attributeOffset], al
2611
        add     edi, eax
2611
        add     edi, eax
2612
; $StandardInformation
2612
; $StandardInformation
2613
        mov     byte [edi+attributeType], 10h
2613
        mov     byte [edi+attributeType], 10h
2614
        mov     byte [edi+sizeWithHeader], 48h
2614
        mov     byte [edi+sizeWithHeader], 48h
2615
        mov     byte [edi+sizeWithoutHeader], 30h
2615
        mov     byte [edi+sizeWithoutHeader], 30h
2616
        mov     byte [edi+attributeOffset], 18h
2616
        mov     byte [edi+attributeOffset], 18h
2617
        mov     cl, 8
2617
        mov     cl, 8
2618
        add     esi, fileCreated
2618
        add     esi, fileCreated
2619
        add     edi, 18h
2619
        add     edi, 18h
2620
        rep movsd
2620
        rep movsd
2621
        add     edi, 16
2621
        add     edi, 16
2622
        mov     esi, [ebp+NTFS.indexPointer]
2622
        mov     esi, [ebp+NTFS.indexPointer]
2623
; $FileName
2623
; $FileName
2624
        mov     byte [edi+attributeType], 30h
2624
        mov     byte [edi+attributeType], 30h
2625
        mov     byte [edi+attributeID], 1
2625
        mov     byte [edi+attributeID], 1
2626
        mov     byte [edi+attributeOffset], 18h
2626
        mov     byte [edi+attributeOffset], 18h
2627
        mov     byte [edi+indexedFlag], 1
2627
        mov     byte [edi+indexedFlag], 1
2628
        mov     cx, [esi+indexRawSize]
2628
        mov     cx, [esi+indexRawSize]
2629
        mov     [edi+sizeWithoutHeader], ecx
2629
        mov     [edi+sizeWithoutHeader], ecx
2630
        mov     cx, [esi+indexAllocatedSize]
2630
        mov     cx, [esi+indexAllocatedSize]
2631
        add     ecx, 8
2631
        add     ecx, 8
2632
        mov     [edi+sizeWithHeader], ecx
2632
        mov     [edi+sizeWithHeader], ecx
2633
        add     edi, 18h
2633
        add     edi, 18h
2634
        add     esi, 16
2634
        add     esi, 16
2635
        sub     ecx, 18h
2635
        sub     ecx, 18h
2636
        shr     ecx, 2
2636
        shr     ecx, 2
2637
        rep movsd
2637
        rep movsd
2638
        mov     byte [edi+sizeWithHeader], 50h
2638
        mov     byte [edi+sizeWithHeader], 50h
2639
        mov     byte [edi+attributeID], 2
2639
        mov     byte [edi+attributeID], 2
2640
        cmp     [ebp+NTFS.bFolder], 1
2640
        cmp     [ebp+NTFS.bFolder], 1
2641
        jz      .indexRoot
2641
        jz      .indexRoot
2642
; $Data
2642
; $Data
2643
        mov     byte [edi+attributeType], 80h
2643
        mov     byte [edi+attributeType], 80h
2644
        mov     eax, [ebp+NTFS.fileDataSize]
2644
        mov     eax, [ebp+NTFS.fileDataSize]
2645
        test    eax, eax
2645
        test    eax, eax
2646
        jz      .resident
2646
        jz      .resident
2647
        mov     esi, [ebp+NTFS.indexPointer]
2647
        mov     esi, [ebp+NTFS.indexPointer]
2648
        dec     eax
2648
        dec     eax
2649
        mov     [edi+lastVCN], eax
2649
        mov     [edi+lastVCN], eax
2650
        mov     byte [edi+nonResidentFlag], 1
2650
        mov     byte [edi+nonResidentFlag], 1
2651
        mov     byte [edi+dataRunsOffset], 40h
2651
        mov     byte [edi+dataRunsOffset], 40h
2652
        mov     eax, [esi+fileAllocatedSize]
2652
        mov     eax, [esi+fileAllocatedSize]
2653
        mov     [edi+attributeAllocatedSize], eax
2653
        mov     [edi+attributeAllocatedSize], eax
2654
        mov     eax, [esi+fileRealSize]
2654
        mov     eax, [esi+fileRealSize]
2655
        mov     [edi+attributeRealSize], eax
2655
        mov     [edi+attributeRealSize], eax
2656
        mov     [edi+initialDataSize], eax
2656
        mov     [edi+initialDataSize], eax
2657
        push    edi
2657
        push    edi
2658
        mov     esi, edi
2658
        mov     esi, edi
2659
        add     edi, 40h
2659
        add     edi, 40h
2660
        call    createMcbEntry
2660
        call    createMcbEntry
2661
        inc     edi
2661
        inc     edi
2662
        jmp     @f
2662
        jmp     @f
2663
 
2663
 
2664
.resident:
2664
.resident:
2665
        mov     ecx, [ebp+NTFS.fileRealSize]
2665
        mov     ecx, [ebp+NTFS.fileRealSize]
2666
        mov     [edi+sizeWithoutHeader], ecx
2666
        mov     [edi+sizeWithoutHeader], ecx
2667
        mov     byte [edi+attributeOffset], 18h
2667
        mov     byte [edi+attributeOffset], 18h
2668
        push    edi
2668
        push    edi
2669
        mov     esi, [ebp+NTFS.fileDataBuffer]
2669
        mov     esi, [ebp+NTFS.fileDataBuffer]
2670
        add     edi, 18h
2670
        add     edi, 18h
2671
        rep movsb
2671
        rep movsb
2672
@@:
2672
@@:
2673
        mov     eax, edi
2673
        mov     eax, edi
2674
        pop     edi
2674
        pop     edi
2675
        sub     eax, edi
2675
        sub     eax, edi
2676
        add     eax, 7
2676
        add     eax, 7
2677
        and     eax, not 7
2677
        and     eax, not 7
2678
        mov     [edi+sizeWithHeader], eax
2678
        mov     [edi+sizeWithHeader], eax
2679
        add     edi, eax
2679
        add     edi, eax
2680
        mov     al, 1
2680
        mov     al, 1
2681
        jmp     .end
2681
        jmp     .end
2682
 
2682
 
2683
.indexRoot:
2683
.indexRoot:
2684
        mov     byte [edi+attributeType], 90h
2684
        mov     byte [edi+attributeType], 90h
2685
        mov     byte [edi+nameLength], 4
2685
        mov     byte [edi+nameLength], 4
2686
        mov     byte [edi+nameOffset], 18h
2686
        mov     byte [edi+nameOffset], 18h
2687
        mov     byte [edi+sizeWithoutHeader], 30h
2687
        mov     byte [edi+sizeWithoutHeader], 30h
2688
        mov     byte [edi+attributeOffset], 20h
2688
        mov     byte [edi+attributeOffset], 20h
2689
        mov     dword[edi+18h], 490024h     ; unicode $I30
2689
        mov     dword[edi+18h], 490024h     ; unicode $I30
2690
        mov     dword[edi+18h+4], 300033h
2690
        mov     dword[edi+18h+4], 300033h
2691
        mov     byte [edi+20h+indexedAttributesType], 30h
2691
        mov     byte [edi+20h+indexedAttributesType], 30h
2692
        mov     byte [edi+20h+collationRule], 1
2692
        mov     byte [edi+20h+collationRule], 1
2693
        mov     eax, [ebp+NTFS.sectors_per_cluster]
2693
        mov     eax, [ebp+NTFS.sectors_per_cluster]
2694
        mov     dl, 1
2694
        mov     dl, 1
2695
        shl     eax, 8
2695
        shl     eax, 8
2696
@@:
2696
@@:
2697
        shl     eax, 1
2697
        shl     eax, 1
2698
        shl     edx, 1
2698
        shl     edx, 1
2699
        cmp     eax, [ebp+NTFS.frs_size]
2699
        cmp     eax, [ebp+NTFS.frs_size]
2700
        jc      @b
2700
        jc      @b
2701
        shr     edx, 1
2701
        shr     edx, 1
2702
        mov     [edi+20h+indexRecordSize], eax
2702
        mov     [edi+20h+indexRecordSize], eax
2703
        mov     [edi+20h+indexRecordSizeClus], dl
2703
        mov     [edi+20h+indexRecordSizeClus], dl
2704
        mov     byte [edi+30h+indexOffset], 16
2704
        mov     byte [edi+30h+indexOffset], 16
2705
        mov     byte [edi+30h+nodeRealSize], 32
2705
        mov     byte [edi+30h+nodeRealSize], 32
2706
        mov     byte [edi+30h+nodeAllocatedSize], 32
2706
        mov     byte [edi+30h+nodeAllocatedSize], 32
2707
        mov     byte [edi+40h+indexAllocatedSize], 16
2707
        mov     byte [edi+40h+indexAllocatedSize], 16
2708
        mov     byte [edi+40h+indexFlags], 2
2708
        mov     byte [edi+40h+indexFlags], 2
2709
        add     edi, 50h
2709
        add     edi, 50h
2710
        mov     al, 3
2710
        mov     al, 3
2711
.end:
2711
.end:
2712
        mov     ebx, [ebp+NTFS.frs_buffer]
2712
        mov     ebx, [ebp+NTFS.frs_buffer]
2713
        mov     dword [edi], -1
2713
        mov     dword [edi], -1
2714
        mov     dword [edi+4], 0
2714
        mov     dword [edi+4], 0
2715
        add     edi, 8
2715
        add     edi, 8
2716
        sub     edi, ebx
2716
        sub     edi, ebx
2717
        mov     [ebx+recordFlags], al
2717
        mov     [ebx+recordFlags], al
2718
        mov     [ebx+recordRealSize], edi
2718
        mov     [ebx+recordRealSize], edi
2719
        mov     edx, [ebp+NTFS.LastRead]
2719
        mov     edx, [ebp+NTFS.LastRead]
2720
        call    writeRecord
2720
        call    writeRecord
2721
; write MFT bitmap
2721
; write MFT bitmap
2722
        mov     eax, [ebp+NTFS.newRecord]
2722
        mov     eax, [ebp+NTFS.newRecord]
2723
        shr     eax, 3+9
2723
        shr     eax, 3+9
2724
        mov     ebx, eax
2724
        mov     ebx, eax
2725
        shl     ebx, 9
2725
        shl     ebx, 9
2726
        add     eax, [ebp+NTFS.mftBitmapLocation]
2726
        add     eax, [ebp+NTFS.mftBitmapLocation]
2727
        add     ebx, [ebp+NTFS.mftBitmapBuffer]
2727
        add     ebx, [ebp+NTFS.mftBitmapBuffer]
2728
        mov     ecx, 1
2728
        mov     ecx, 1
2729
        xor     edx, edx
2729
        xor     edx, edx
2730
        call    fs_write64_sys
2730
        call    fs_write64_sys
2731
; 5. Write directory node
2731
; 5. Write directory node
2732
        mov     ebx, [ebp+NTFS.cur_index_buf]
2732
        mov     ebx, [ebp+NTFS.cur_index_buf]
2733
        mov     edx, [ebp+NTFS.nodeLastRead]
2733
        mov     edx, [ebp+NTFS.nodeLastRead]
2734
        call    writeRecord
2734
        call    writeRecord
2735
        mov     ebx, [ebp+NTFS.fileRealSize]
2735
        mov     ebx, [ebp+NTFS.fileRealSize]
2736
ntfsDone:
2736
ntfsDone:
2737
        mov     esi, [ebp+PARTITION.Disk]
2737
        mov     esi, [ebp+PARTITION.Disk]
2738
        call    disk_sync
2738
        call    disk_sync
2739
        call    ntfs_unlock
2739
        call    ntfs_unlock
2740
        xor     eax, eax
2740
        xor     eax, eax
2741
        ret
2741
        ret
2742
 
2742
 
2743
writeRecord:
2743
writeRecord:
2744
; make updateSequence and write to disk
2744
; make updateSequence and write to disk
2745
;   in:
2745
;   in:
2746
; ebx -> record
2746
; ebx -> record
2747
; edx = partition sector
2747
; edx = partition sector
2748
        mov     esi, ebx
2748
        mov     esi, ebx
2749
        mov     edi, ebx
2749
        mov     edi, ebx
2750
        movzx   ecx, word [esi+updateSequenceOffset]
2750
        movzx   ecx, word [esi+updateSequenceOffset]
2751
        add     edi, ecx
2751
        add     edi, ecx
2752
        mov     ax, [edi]
2752
        mov     ax, [edi]
2753
        inc     ax
2753
        inc     ax
2754
        stosw
2754
        stosw
2755
        mov     cx, [esi+updateSequenceSize]
2755
        mov     cx, [esi+updateSequenceSize]
2756
        dec     ecx
2756
        dec     ecx
2757
        push    ecx
2757
        push    ecx
2758
@@:
2758
@@:
2759
        add     esi, 510
2759
        add     esi, 510
2760
        movsw
2760
        movsw
2761
        mov     [esi-2], ax
2761
        mov     [esi-2], ax
2762
        loop    @b
2762
        loop    @b
2763
        mov     eax, edx
2763
        mov     eax, edx
2764
        xor     edx, edx
2764
        xor     edx, edx
2765
        pop     ecx
2765
        pop     ecx
2766
        jmp     fs_write64_sys
2766
        jmp     fs_write64_sys
2767
 
2767
 
2768
createMcbEntry:
2768
createMcbEntry:
2769
;   in:
2769
;   in:
2770
; [ebp+NTFS.fileDataStart] = position value
2770
; [ebp+NTFS.fileDataStart] = position value
2771
; [ebp+NTFS.fileDataSize] = size value
2771
; [ebp+NTFS.fileDataSize] = size value
2772
; edi -> destination
2772
; edi -> destination
2773
; esi -> attribute header
2773
; esi -> attribute header
2774
        mov     eax, [ebp+NTFS.fileDataStart]
2774
        mov     eax, [ebp+NTFS.fileDataStart]
2775
        xor     edx, edx
2775
        xor     edx, edx
2776
        shl     eax, 1
2776
        shl     eax, 1
2777
        jnc     @f
2777
        jnc     @f
2778
        not     eax
2778
        not     eax
2779
@@:
2779
@@:
2780
        inc     edx
2780
        inc     edx
2781
        shr     eax, 8
2781
        shr     eax, 8
2782
        jnz     @b
2782
        jnz     @b
2783
        mov     eax, [ebp+NTFS.fileDataSize]
2783
        mov     eax, [ebp+NTFS.fileDataSize]
2784
        shl     eax, 1
2784
        shl     eax, 1
2785
        xor     ecx, ecx
2785
        xor     ecx, ecx
2786
@@:
2786
@@:
2787
        inc     ecx
2787
        inc     ecx
2788
        shr     eax, 8
2788
        shr     eax, 8
2789
        jnz     @b
2789
        jnz     @b
2790
        lea     eax, [edi+edx+1]
2790
        lea     eax, [edi+edx+1]
2791
        add     eax, ecx
2791
        add     eax, ecx
2792
        sub     eax, esi
2792
        sub     eax, esi
2793
        sub     eax, [esi+sizeWithHeader]
2793
        sub     eax, [esi+sizeWithHeader]
2794
        jc      @f
2794
        jc      @f
2795
        add     word [esi+sizeWithHeader], 8    ; extend attribute
2795
        add     word [esi+sizeWithHeader], 8    ; extend attribute
2796
        mov     esi, [ebp+NTFS.frs_buffer]
2796
        mov     esi, [ebp+NTFS.frs_buffer]
2797
        mov     eax, [esi+recordRealSize]
2797
        mov     eax, [esi+recordRealSize]
2798
        add     eax, 8
2798
        add     eax, 8
2799
        cmp     [esi+recordAllocatedSize], eax
2799
        cmp     [esi+recordAllocatedSize], eax
2800
        jc      .end    ; no space in the record
2800
        jc      .end    ; no space in the record
2801
        mov     [esi+recordRealSize], eax
2801
        mov     [esi+recordRealSize], eax
2802
        push    ecx edi
2802
        push    ecx edi
2803
        add     esi, eax
2803
        add     esi, eax
2804
        mov     ecx, esi
2804
        mov     ecx, esi
2805
        sub     ecx, edi
2805
        sub     ecx, edi
2806
        sub     ecx, 8
2806
        sub     ecx, 8
2807
        shr     ecx, 2
2807
        shr     ecx, 2
2808
        mov     edi, esi
2808
        mov     edi, esi
2809
        sub     edi, 4
2809
        sub     edi, 4
2810
        sub     esi, 12
2810
        sub     esi, 12
2811
        std
2811
        std
2812
        rep movsd
2812
        rep movsd
2813
        cld
2813
        cld
2814
        pop     edi ecx
2814
        pop     edi ecx
2815
@@:
2815
@@:
2816
        mov     eax, edx
2816
        mov     eax, edx
2817
        shl     eax, 4
2817
        shl     eax, 4
2818
        add     eax, ecx
2818
        add     eax, ecx
2819
        stosb
2819
        stosb
2820
        lea     esi, [ebp+NTFS.fileDataSize]
2820
        lea     esi, [ebp+NTFS.fileDataSize]
2821
        rep movsb
2821
        rep movsb
2822
        lea     esi, [ebp+NTFS.fileDataStart]
2822
        lea     esi, [ebp+NTFS.fileDataStart]
2823
        mov     ecx, edx
2823
        mov     ecx, edx
2824
        rep movsb
2824
        rep movsb
2825
        mov     [edi], cl
2825
        mov     [edi], cl
2826
.end:
2826
.end:
2827
        ret
2827
        ret
2828
 
2828
 
2829
resizeAttribute:
2829
resizeAttribute:
2830
;   in:
2830
;   in:
2831
; [ebp+NTFS.frs_buffer] -> file record
2831
; [ebp+NTFS.frs_buffer] -> file record
2832
; [ebp+NTFS.attr_offs] -> attribute
2832
; [ebp+NTFS.attr_offs] -> attribute
2833
; edx:eax = new size
2833
; edx:eax = new size
2834
;   out:
2834
;   out:
2835
; [ebp+NTFS.fileDataSize] = clusters added (positive)
2835
; [ebp+NTFS.fileDataSize] = clusters added (positive)
2836
; [ebp+NTFS.fileDataStart] = added block
2836
; [ebp+NTFS.fileDataStart] = added block
2837
; CF=1 -> eax = error code
2837
; CF=1 -> eax = error code
2838
        mov     esi, [ebp+NTFS.attr_offs]
2838
        mov     esi, [ebp+NTFS.attr_offs]
2839
        mov     dword [ebp+NTFS.attr_size], eax
2839
        mov     dword [ebp+NTFS.attr_size], eax
2840
        mov     dword [ebp+NTFS.attr_size+4], edx
2840
        mov     dword [ebp+NTFS.attr_size+4], edx
2841
        cmp     byte [esi+nonResidentFlag], 0
2841
        cmp     byte [esi+nonResidentFlag], 0
2842
        jz      .resident
2842
        jz      .resident
2843
        mov     ecx, [ebp+NTFS.sectors_per_cluster]
2843
        mov     ecx, [ebp+NTFS.sectors_per_cluster]
2844
        shl     ecx, 9
2844
        shl     ecx, 9
2845
        mov     [esi+attributeRealSize], eax
2845
        mov     [esi+attributeRealSize], eax
2846
        mov     [esi+attributeRealSize+4], edx
2846
        mov     [esi+attributeRealSize+4], edx
2847
        mov     [esi+initialDataSize], eax
2847
        mov     [esi+initialDataSize], eax
2848
        mov     [esi+initialDataSize+4], edx
2848
        mov     [esi+initialDataSize+4], edx
2849
        sub     eax, 1
2849
        sub     eax, 1
2850
        sbb     edx, 0
2850
        sbb     edx, 0
2851
        jc      .makeResident
2851
        jc      .makeResident
2852
        div     ecx
2852
        div     ecx
2853
        mov     edi, eax
2853
        mov     edi, eax
2854
        inc     eax
2854
        inc     eax
2855
        mul     ecx
2855
        mul     ecx
2856
        mov     [esi+attributeAllocatedSize], eax
2856
        mov     [esi+attributeAllocatedSize], eax
2857
        mov     [esi+attributeAllocatedSize+4], edx
2857
        mov     [esi+attributeAllocatedSize+4], edx
2858
        mov     ecx, [esi+lastVCN]
2858
        mov     ecx, [esi+lastVCN]
2859
        mov     [esi+lastVCN], edi
2859
        mov     [esi+lastVCN], edi
2860
        movzx   eax, byte [esi+dataRunsOffset]
2860
        movzx   eax, byte [esi+dataRunsOffset]
2861
        sub     edi, ecx
2861
        sub     edi, ecx
2862
        mov     [ebp+NTFS.fileDataSize], edi
2862
        mov     [ebp+NTFS.fileDataSize], edi
2863
        jz      .done
2863
        jz      .done
2864
        jc      .shrinkAttribute
2864
        jc      .shrinkAttribute
2865
; extend attribute
2865
; extend attribute
2866
        xor     edi, edi
2866
        xor     edi, edi
2867
        add     esi, eax
2867
        add     esi, eax
2868
        push    edi edi edi edi
2868
        push    edi edi edi edi
2869
@@:
2869
@@:
2870
        mov     edx, eax
2870
        mov     edx, eax
2871
        mov     eax, esi
2871
        mov     eax, esi
2872
        add     edi, [esp+8]
2872
        add     edi, [esp+8]
2873
        call    ntfs_decode_mcb_entry
2873
        call    ntfs_decode_mcb_entry
2874
        jc      @b
2874
        jc      @b
2875
        mov     [esp+4], edx
2875
        mov     [esp+4], edx
2876
        mov     [esp+12], edi
2876
        mov     [esp+12], edi
2877
        add     edi, [esp]
2877
        add     edi, [esp]
2878
        push    edi
2878
        push    edi
2879
        shr     edi, 5
2879
        shr     edi, 5
2880
        shl     edi, 2
2880
        shl     edi, 2
2881
        push    eax
2881
        push    eax
2882
        cmp     edi, [ebp+NTFS.BitmapStart]
2882
        cmp     edi, [ebp+NTFS.BitmapStart]
2883
        jnc     @f
2883
        jnc     @f
2884
        cmp     [ebp+NTFS.cur_iRecord], 0
2884
        cmp     [ebp+NTFS.cur_iRecord], 0
2885
        jz      @f
2885
        jz      @f
2886
        mov     edi, [ebp+NTFS.BitmapStart]
2886
        mov     edi, [ebp+NTFS.BitmapStart]
2887
@@:
2887
@@:
2888
        call    ntfsSpaceAlloc
2888
        call    ntfsSpaceAlloc
2889
        jc      .err1
2889
        jc      .err1
2890
        mov     eax, [ebp+NTFS.fileDataStart]
2890
        mov     eax, [ebp+NTFS.fileDataStart]
2891
        pop     edi
2891
        pop     edi
2892
        pop     edx
2892
        pop     edx
2893
        cmp     edx, eax
2893
        cmp     edx, eax
2894
        jnz     .newEntry
2894
        jnz     .newEntry
2895
        pop     edx
2895
        pop     edx
2896
        pop     edi
2896
        pop     edi
2897
        pop     [ebp+NTFS.fileDataStart]
2897
        pop     [ebp+NTFS.fileDataStart]
2898
        mov     [esp], eax
2898
        mov     [esp], eax
2899
        push    [ebp+NTFS.fileDataSize]
2899
        push    [ebp+NTFS.fileDataSize]
2900
        add     [ebp+NTFS.fileDataSize], edx
2900
        add     [ebp+NTFS.fileDataSize], edx
2901
        jmp     @f
2901
        jmp     @f
2902
 
2902
 
2903
.newEntry:
2903
.newEntry:
2904
        add     esp, 12
2904
        add     esp, 12
2905
        pop     edx
2905
        pop     edx
2906
        push    eax
2906
        push    eax
2907
        push    [ebp+NTFS.fileDataSize]
2907
        push    [ebp+NTFS.fileDataSize]
2908
        sub     eax, edx
2908
        sub     eax, edx
2909
        mov     [ebp+NTFS.fileDataStart], eax
2909
        mov     [ebp+NTFS.fileDataStart], eax
2910
@@:
2910
@@:
2911
        mov     esi, [ebp+NTFS.attr_offs]
2911
        mov     esi, [ebp+NTFS.attr_offs]
2912
        call    createMcbEntry
2912
        call    createMcbEntry
2913
        pop     [ebp+NTFS.fileDataSize]
2913
        pop     [ebp+NTFS.fileDataSize]
2914
        pop     [ebp+NTFS.fileDataStart]
2914
        pop     [ebp+NTFS.fileDataStart]
2915
        movi    eax, ERROR_UNSUPPORTED_FS
2915
        movi    eax, ERROR_UNSUPPORTED_FS
2916
.done:
2916
.done:
2917
        ret
2917
        ret
2918
 
2918
 
2919
.err1:
2919
.err1:
2920
        add     esp, 24
2920
        add     esp, 24
2921
        stc
2921
        stc
2922
.err2:
2922
.err2:
2923
        movi    eax, ERROR_DISK_FULL
2923
        movi    eax, ERROR_DISK_FULL
2924
        ret
2924
        ret
2925
 
2925
 
2926
.err3:
2926
.err3:
2927
        movi    eax, ERROR_FS_FAIL
2927
        movi    eax, ERROR_FS_FAIL
2928
        add     esp, 20
2928
        add     esp, 20
2929
        stc
2929
        stc
2930
        ret
2930
        ret
2931
 
2931
 
2932
.shrinkAttribute:
2932
.shrinkAttribute:
2933
        add     ecx, edi
2933
        add     ecx, edi
2934
        inc     ecx
2934
        inc     ecx
2935
        add     esi, eax
2935
        add     esi, eax
2936
        xor     edi, edi
2936
        xor     edi, edi
2937
        sub     esp, 20
2937
        sub     esp, 20
2938
@@:
2938
@@:
2939
        mov     [esp+16], esi
2939
        mov     [esp+16], esi
2940
        call    ntfs_decode_mcb_entry
2940
        call    ntfs_decode_mcb_entry
2941
        jnc     .err3
2941
        jnc     .err3
2942
        add     edi, [esp+8]
2942
        add     edi, [esp+8]
2943
        sub     ecx, [esp]
2943
        sub     ecx, [esp]
2944
        jnc     @b
2944
        jnc     @b
2945
        mov     ebx, ecx
2945
        mov     ebx, ecx
2946
        add     ecx, [esp]
2946
        add     ecx, [esp]
2947
        mov     eax, [esp+8]
2947
        mov     eax, [esp+8]
2948
        mov     [ebp+NTFS.fileDataSize], ecx
2948
        mov     [ebp+NTFS.fileDataSize], ecx
2949
        mov     [ebp+NTFS.fileDataStart], eax
2949
        mov     [ebp+NTFS.fileDataStart], eax
2950
        push    edi
2950
        push    edi
2951
        add     edi, ecx
2951
        add     edi, ecx
2952
        neg     ebx
2952
        neg     ebx
2953
        call    ntfsSpaceFree
2953
        call    ntfsSpaceFree
2954
        pop     edi
2954
        pop     edi
2955
        jc      .end
2955
        jc      .end
2956
@@:
2956
@@:
2957
        call    ntfs_decode_mcb_entry
2957
        call    ntfs_decode_mcb_entry
2958
        jnc     .end
2958
        jnc     .end
2959
        cmp     dword[esp+8], 0
2959
        cmp     dword[esp+8], 0
2960
        jz      @b
2960
        jz      @b
2961
        add     edi, [esp+8]
2961
        add     edi, [esp+8]
2962
        mov     ebx, [esp]
2962
        mov     ebx, [esp]
2963
        call    ntfsSpaceFree
2963
        call    ntfsSpaceFree
2964
        jnc     @b
2964
        jnc     @b
2965
.end:
2965
.end:
2966
        add     esp, 16
2966
        add     esp, 16
2967
        pop     edi
2967
        pop     edi
2968
        cmp     [ebp+NTFS.fileDataSize], 0
2968
        cmp     [ebp+NTFS.fileDataSize], 0
2969
        jz      @f
2969
        jz      @f
2970
        mov     esi, [ebp+NTFS.attr_offs]
2970
        mov     esi, [ebp+NTFS.attr_offs]
2971
        call    createMcbEntry
2971
        call    createMcbEntry
2972
        mov     [ebp+NTFS.fileDataSize], 0
2972
        mov     [ebp+NTFS.fileDataSize], 0
2973
@@:
2973
@@:
2974
        ret
2974
        ret
2975
 
2975
 
2976
.resident:
2976
.resident:
2977
        test    edx, edx
2977
        test    edx, edx
2978
        jnz     .nonResident
2978
        jnz     .nonResident
2979
        cmp     eax, 8000h
2979
        cmp     eax, 8000h
2980
        jnc     .nonResident
2980
        jnc     .nonResident
2981
        add     ax, [esi+attributeOffset]
2981
        add     ax, [esi+attributeOffset]
2982
        sub     eax, [esi+sizeWithHeader]
2982
        sub     eax, [esi+sizeWithHeader]
2983
        jc      @f
2983
        jc      @f
2984
        mov     edi, [ebp+NTFS.frs_buffer]
2984
        mov     edi, [ebp+NTFS.frs_buffer]
2985
        mov     ecx, eax
2985
        mov     ecx, eax
2986
        add     ecx, [edi+recordRealSize]
2986
        add     ecx, [edi+recordRealSize]
2987
        cmp     [edi+recordAllocatedSize], ecx
2987
        cmp     [edi+recordAllocatedSize], ecx
2988
        jc      .nonResident
2988
        jc      .nonResident
2989
        add     eax, 7
2989
        add     eax, 7
2990
        and     eax, not 7
2990
        and     eax, not 7
2991
        add     [edi+recordRealSize], eax
2991
        add     [edi+recordRealSize], eax
2992
        add     edi, [edi+recordRealSize]
2992
        add     edi, [edi+recordRealSize]
2993
        add     [esi+sizeWithHeader], eax
2993
        add     [esi+sizeWithHeader], eax
2994
        add     esi, [esi+sizeWithHeader]
2994
        add     esi, [esi+sizeWithHeader]
2995
        mov     ecx, edi
2995
        mov     ecx, edi
2996
        sub     ecx, esi
2996
        sub     ecx, esi
2997
        shr     ecx, 2
2997
        shr     ecx, 2
2998
        sub     edi, 4
2998
        sub     edi, 4
2999
        mov     esi, edi
2999
        mov     esi, edi
3000
        sub     esi, eax
3000
        sub     esi, eax
3001
        std
3001
        std
3002
        rep movsd
3002
        rep movsd
3003
        mov     ecx, eax
3003
        mov     ecx, eax
3004
        shr     ecx, 2
3004
        shr     ecx, 2
3005
        xor     eax, eax
3005
        xor     eax, eax
3006
        rep stosd
3006
        rep stosd
3007
        cld
3007
        cld
3008
        mov     esi, [ebp+NTFS.attr_offs]
3008
        mov     esi, [ebp+NTFS.attr_offs]
3009
@@:
3009
@@:
3010
        mov     eax, dword [ebp+NTFS.attr_size]
3010
        mov     eax, dword [ebp+NTFS.attr_size]
3011
        mov     [esi+sizeWithoutHeader], eax
3011
        mov     [esi+sizeWithoutHeader], eax
3012
        mov     [ebp+NTFS.fileDataSize], 0
3012
        mov     [ebp+NTFS.fileDataSize], 0
3013
        clc
3013
        clc
3014
        ret
3014
        ret
3015
 
3015
 
3016
.nonResident:   ; convert resident to non-resident
3016
.nonResident:   ; convert resident to non-resident
3017
        mov     eax, dword [ebp+NTFS.attr_size]
3017
        mov     eax, dword [ebp+NTFS.attr_size]
3018
        sub     eax, 1
3018
        sub     eax, 1
3019
        sbb     edx, 0
3019
        sbb     edx, 0
3020
        mov     ecx, [ebp+NTFS.sectors_per_cluster]
3020
        mov     ecx, [ebp+NTFS.sectors_per_cluster]
3021
        shl     ecx, 9
3021
        shl     ecx, 9
3022
        div     ecx
3022
        div     ecx
3023
        inc     eax
3023
        inc     eax
3024
        mov     [ebp+NTFS.fileDataSize], eax
3024
        mov     [ebp+NTFS.fileDataSize], eax
3025
        mov     edi, [ebp+NTFS.BitmapStart]
3025
        mov     edi, [ebp+NTFS.BitmapStart]
3026
        push    ecx
3026
        push    ecx
3027
        call    ntfsSpaceAlloc
3027
        call    ntfsSpaceAlloc
3028
        pop     ecx
3028
        pop     ecx
3029
        jc      .err2
3029
        jc      .err2
3030
        mov     esi, [ebp+NTFS.attr_offs]
3030
        mov     esi, [ebp+NTFS.attr_offs]
3031
        xor     eax, eax
3031
        xor     eax, eax
3032
        xor     edx, edx
3032
        xor     edx, edx
3033
@@:
3033
@@:
3034
        add     eax, ecx
3034
        add     eax, ecx
3035
        inc     edx
3035
        inc     edx
3036
        cmp     eax, [esi+sizeWithoutHeader]
3036
        cmp     eax, [esi+sizeWithoutHeader]
3037
        jc      @b
3037
        jc      @b
3038
        push    edx
3038
        push    edx
3039
        push    eax
3039
        push    eax
3040
        stdcall kernel_alloc, eax
3040
        stdcall kernel_alloc, eax
3041
        mov     ecx, [esp]
3041
        mov     ecx, [esp]
3042
        shr     ecx, 2
3042
        shr     ecx, 2
3043
        mov     edi, eax
3043
        mov     edi, eax
3044
        mov     ebx, eax
3044
        mov     ebx, eax
3045
        xor     eax, eax
3045
        xor     eax, eax
3046
        rep stosd
3046
        rep stosd
3047
        mov     al, [esi+attributeOffset]
3047
        mov     al, [esi+attributeOffset]
3048
        mov     ecx, [esi+sizeWithoutHeader]
3048
        mov     ecx, [esi+sizeWithoutHeader]
3049
        add     esi, eax
3049
        add     esi, eax
3050
        mov     edi, ebx
3050
        mov     edi, ebx
3051
        rep movsb
3051
        rep movsb
3052
        mov     eax, [ebp+NTFS.fileDataStart]
3052
        mov     eax, [ebp+NTFS.fileDataStart]
3053
        mul     [ebp+NTFS.sectors_per_cluster]
3053
        mul     [ebp+NTFS.sectors_per_cluster]
3054
        pop     ecx
3054
        pop     ecx
3055
        shr     ecx, 9
3055
        shr     ecx, 9
3056
        call    fs_write64_app
3056
        call    fs_write64_app
3057
        stdcall kernel_free, ebx
3057
        stdcall kernel_free, ebx
3058
        mov     esi, [ebp+NTFS.attr_offs]
3058
        mov     esi, [ebp+NTFS.attr_offs]
3059
        add     esi, [esi+sizeWithHeader]
3059
        add     esi, [esi+sizeWithHeader]
3060
        mov     ecx, [ebp+NTFS.frs_buffer]
3060
        mov     ecx, [ebp+NTFS.frs_buffer]
3061
        add     ecx, [ecx+recordRealSize]
3061
        add     ecx, [ecx+recordRealSize]
3062
        sub     ecx, esi
3062
        sub     ecx, esi
3063
        shr     ecx, 2
3063
        shr     ecx, 2
3064
        lea     edi, [ebp+NTFS.bitmap_buf]
3064
        lea     edi, [ebp+NTFS.bitmap_buf]
3065
        push    ecx
3065
        push    ecx
3066
        rep movsd
3066
        rep movsd
3067
        mov     edi, [ebp+NTFS.attr_offs]
3067
        mov     edi, [ebp+NTFS.attr_offs]
3068
        add     edi, 16
3068
        add     edi, 16
3069
        mov     cl, 6
3069
        mov     cl, 6
3070
        xor     eax, eax
3070
        xor     eax, eax
3071
        rep stosd
3071
        rep stosd
3072
        mov     edi, [ebp+NTFS.attr_offs]
3072
        mov     edi, [ebp+NTFS.attr_offs]
3073
        mov     eax, [ebp+NTFS.fileDataSize]
3073
        mov     eax, [ebp+NTFS.fileDataSize]
3074
        dec     eax
3074
        dec     eax
3075
        mov     [edi+lastVCN], eax
3075
        mov     [edi+lastVCN], eax
3076
        inc     eax
3076
        inc     eax
3077
        mov     ecx, [ebp+NTFS.sectors_per_cluster]
3077
        mov     ecx, [ebp+NTFS.sectors_per_cluster]
3078
        shl     ecx, 9
3078
        shl     ecx, 9
3079
        mul     ecx
3079
        mul     ecx
3080
        mov     byte [edi+sizeWithHeader], 50h
3080
        mov     byte [edi+sizeWithHeader], 50h
3081
        mov     byte [edi+nonResidentFlag], 1
3081
        mov     byte [edi+nonResidentFlag], 1
3082
        mov     byte [edi+dataRunsOffset], 40h
3082
        mov     byte [edi+dataRunsOffset], 40h
3083
        mov     [edi+attributeAllocatedSize], eax
3083
        mov     [edi+attributeAllocatedSize], eax
3084
        mov     [edi+attributeAllocatedSize+4], edx
3084
        mov     [edi+attributeAllocatedSize+4], edx
3085
        mov     eax, dword [ebp+NTFS.attr_size]
3085
        mov     eax, dword [ebp+NTFS.attr_size]
3086
        mov     edx, dword [ebp+NTFS.attr_size+4]
3086
        mov     edx, dword [ebp+NTFS.attr_size+4]
3087
        mov     [edi+attributeRealSize], eax
3087
        mov     [edi+attributeRealSize], eax
3088
        mov     [edi+attributeRealSize+4], edx
3088
        mov     [edi+attributeRealSize+4], edx
3089
        mov     [edi+initialDataSize], eax
3089
        mov     [edi+initialDataSize], eax
3090
        mov     [edi+initialDataSize+4], edx
3090
        mov     [edi+initialDataSize+4], edx
3091
        mov     esi, edi
3091
        mov     esi, edi
3092
        add     edi, 40h
3092
        add     edi, 40h
3093
        call    createMcbEntry
3093
        call    createMcbEntry
3094
        mov     eax, edi
3094
        mov     eax, edi
3095
        mov     edi, [ebp+NTFS.attr_offs]
3095
        mov     edi, [ebp+NTFS.attr_offs]
3096
        sub     eax, edi
3096
        sub     eax, edi
3097
        add     eax, 8
3097
        add     eax, 8
3098
        and     eax, not 7
3098
        and     eax, not 7
3099
        mov     [edi+sizeWithHeader], eax
3099
        mov     [edi+sizeWithHeader], eax
3100
        pop     ecx
3100
        pop     ecx
3101
        lea     esi, [ebp+NTFS.bitmap_buf]
3101
        lea     esi, [ebp+NTFS.bitmap_buf]
3102
        add     edi, eax
3102
        add     edi, eax
3103
        rep movsd
3103
        rep movsd
3104
        mov     esi, [ebp+NTFS.frs_buffer]
3104
        mov     esi, [ebp+NTFS.frs_buffer]
3105
        sub     edi, esi
3105
        sub     edi, esi
3106
        mov     [esi+recordRealSize], edi
3106
        mov     [esi+recordRealSize], edi
3107
        pop     edx
3107
        pop     edx
3108
        sub     [ebp+NTFS.fileDataSize], edx
3108
        sub     [ebp+NTFS.fileDataSize], edx
3109
        add     [ebp+NTFS.fileDataStart], edx
3109
        add     [ebp+NTFS.fileDataStart], edx
3110
        ret
3110
        ret
3111
 
3111
 
3112
.makeResident:  ; convert non-resident to empty resident
3112
.makeResident:  ; convert non-resident to empty resident
3113
        movzx   eax, byte [esi+dataRunsOffset]
3113
        movzx   eax, byte [esi+dataRunsOffset]
3114
        mov     byte [esi+nonResidentFlag], 0
3114
        mov     byte [esi+nonResidentFlag], 0
3115
        mov     dword [esi+sizeWithoutHeader], 0
3115
        mov     dword [esi+sizeWithoutHeader], 0
3116
        mov     dword [esi+attributeOffset], 18h
3116
        mov     dword [esi+attributeOffset], 18h
3117
        add     esi, eax
3117
        add     esi, eax
3118
        xor     edi, edi
3118
        xor     edi, edi
3119
        sub     esp, 16
3119
        sub     esp, 16
3120
@@:
3120
@@:
3121
        call    ntfs_decode_mcb_entry
3121
        call    ntfs_decode_mcb_entry
3122
        jnc     @f
3122
        jnc     @f
3123
        cmp     dword[esp+8], 0
3123
        cmp     dword[esp+8], 0
3124
        jz      @b
3124
        jz      @b
3125
        add     edi, [esp+8]
3125
        add     edi, [esp+8]
3126
        mov     ebx, [esp]
3126
        mov     ebx, [esp]
3127
        call    ntfsSpaceFree
3127
        call    ntfsSpaceFree
3128
        jnc     @b
3128
        jnc     @b
3129
@@:
3129
@@:
3130
        add     esp, 16
3130
        add     esp, 16
3131
        mov     [ebp+NTFS.fileDataSize], 0
3131
        mov     [ebp+NTFS.fileDataSize], 0
3132
        ret
3132
        ret
3133
 
3133
 
3134
ntfsSpaceClean:
3134
ntfsSpaceClean:
3135
; clean up to 16 Mb of disk space
3135
; clean up to 16 Mb of disk space
3136
;   in:
3136
;   in:
3137
; [ebp+NTFS.fileDataStart] = block to clean
3137
; [ebp+NTFS.fileDataStart] = block to clean
3138
; [ebp+NTFS.fileDataSize] = block size
3138
; [ebp+NTFS.fileDataSize] = block size
3139
        mov     eax, [ebp+NTFS.fileDataSize]
3139
        mov     eax, [ebp+NTFS.fileDataSize]
3140
        test    eax, eax
3140
        test    eax, eax
3141
        jz      @f
3141
        jz      @f
3142
        mul     [ebp+NTFS.sectors_per_cluster]
3142
        mul     [ebp+NTFS.sectors_per_cluster]
3143
        cmp     eax, 8001h
3143
        cmp     eax, 8001h
3144
        jnc     @f
3144
        jnc     @f
3145
        push    eax
3145
        push    eax
3146
        shl     eax, 9
3146
        shl     eax, 9
3147
        stdcall kernel_alloc, eax
3147
        stdcall kernel_alloc, eax
3148
        pop     ecx
3148
        pop     ecx
3149
        test    eax, eax
3149
        test    eax, eax
3150
        jz      @f
3150
        jz      @f
3151
        push    ecx
3151
        push    ecx
3152
        shl     ecx, 7
3152
        shl     ecx, 7
3153
        mov     edi, eax
3153
        mov     edi, eax
3154
        mov     ebx, eax
3154
        mov     ebx, eax
3155
        xor     eax, eax
3155
        xor     eax, eax
3156
        rep stosd
3156
        rep stosd
3157
        mov     eax, [ebp+NTFS.fileDataStart]
3157
        mov     eax, [ebp+NTFS.fileDataStart]
3158
        mul     [ebp+NTFS.sectors_per_cluster]
3158
        mul     [ebp+NTFS.sectors_per_cluster]
3159
        mov     [ebp+NTFS.LastRead], eax
3159
        mov     [ebp+NTFS.LastRead], eax
3160
        pop     ecx
3160
        pop     ecx
3161
        call    fs_write64_app
3161
        call    fs_write64_app
3162
        stdcall kernel_free, ebx
3162
        stdcall kernel_free, ebx
3163
@@:
3163
@@:
3164
        ret
3164
        ret
3165
 
3165
 
3166
ntfsSpaceAlloc:
3166
ntfsSpaceAlloc:
3167
; allocate disk space
3167
; allocate disk space
3168
;   in:
3168
;   in:
3169
; edi = offset in bitmap to start search from
3169
; edi = offset in bitmap to start search from
3170
; [ebp+NTFS.fileDataSize] = block size in clusters
3170
; [ebp+NTFS.fileDataSize] = block size in clusters
3171
;   out:
3171
;   out:
3172
; [ebp+NTFS.fileDataStart] = allocated block starting cluster
3172
; [ebp+NTFS.fileDataStart] = allocated block starting cluster
3173
; CF=1 -> disk full
3173
; CF=1 -> disk full
3174
        mov     ecx, [ebp+NTFS.BitmapBuffer]
3174
        mov     ecx, [ebp+NTFS.BitmapBuffer]
3175
        add     edi, ecx
3175
        add     edi, ecx
3176
        add     ecx, [ebp+NTFS.BitmapSize]
3176
        add     ecx, [ebp+NTFS.BitmapSize]
3177
        sub     ecx, edi
3177
        sub     ecx, edi
3178
        ja      @f
3178
        ja      @f
3179
        push    eax
3179
        push    eax
3180
        call    bitmapBuffering
3180
        call    bitmapBuffering
3181
        pop     eax
3181
        pop     eax
3182
        shl     ecx, 2
3182
        shl     ecx, 2
3183
@@:
3183
@@:
3184
        shr     ecx, 2
3184
        shr     ecx, 2
3185
        push    ecx
3185
        push    ecx
3186
        mov     eax, [ebp+NTFS.fileDataSize]
3186
        mov     eax, [ebp+NTFS.fileDataSize]
3187
        shr     eax, 5
3187
        shr     eax, 5
3188
        jz      .small
3188
        jz      .small
3189
        mov     ebx, eax    ; bitmap dwords
3189
        mov     ebx, eax    ; bitmap dwords
3190
.start:
3190
.start:
3191
        mov     ecx, [ebp+NTFS.BitmapBuffer]
3191
        mov     ecx, [ebp+NTFS.BitmapBuffer]
3192
        add     ecx, [ebp+NTFS.BitmapSize]
3192
        add     ecx, [ebp+NTFS.BitmapSize]
3193
        sub     ecx, edi
3193
        sub     ecx, edi
3194
        shr     ecx, 2
3194
        shr     ecx, 2
3195
@@:
3195
@@:
3196
        xor     eax, eax
3196
        xor     eax, eax
3197
        repnz scasd         ; search for empty dword
3197
        repnz scasd         ; search for empty dword
3198
        jz      @f
3198
        jz      @f
3199
        call    bitmapBuffering
3199
        call    bitmapBuffering
3200
        jmp     @b
3200
        jmp     @b
3201
@@:
3201
@@:
3202
        cmp     ecx, ebx
3202
        cmp     ecx, ebx
3203
        jnc     @f
3203
        jnc     @f
3204
        call    bitmapBuffering
3204
        call    bitmapBuffering
3205
        jmp     @b
3205
        jmp     @b
3206
@@:
3206
@@:
3207
        sub     edi, 4
3207
        sub     edi, 4
3208
        mov     ecx, ebx
3208
        mov     ecx, ebx
3209
        mov     esi, edi
3209
        mov     esi, edi
3210
        xor     eax, eax
3210
        xor     eax, eax
3211
        repz scasd          ; check following dwords
3211
        repz scasd          ; check following dwords
3212
        jnz     .start
3212
        jnz     .start
3213
        sub     esi, 4
3213
        sub     esi, 4
3214
        mov     eax, [esi]
3214
        mov     eax, [esi]
3215
        xor     edx, edx
3215
        xor     edx, edx
3216
        bsr     edx, eax
3216
        bsr     edx, eax
3217
        inc     edx
3217
        inc     edx
3218
        push    edx         ; starting bit
3218
        push    edx         ; starting bit
3219
        push    esi         ; starting dword
3219
        push    esi         ; starting dword
3220
        add     esi, 4
3220
        add     esi, 4
3221
        neg     edx
3221
        neg     edx
3222
        add     edx, 32
3222
        add     edx, 32
3223
        mov     eax, [ebp+NTFS.fileDataSize]
3223
        mov     eax, [ebp+NTFS.fileDataSize]
3224
        sub     eax, edx
3224
        sub     eax, edx
3225
        mov     edx, eax
3225
        mov     edx, eax
3226
        shr     eax, 5
3226
        shr     eax, 5
3227
        shl     eax, 2
3227
        shl     eax, 2
3228
        add     esi, eax
3228
        add     esi, eax
3229
        mov     eax, [esi]
3229
        mov     eax, [esi]
3230
        bsf     ecx, eax    ; check last dword
3230
        bsf     ecx, eax    ; check last dword
3231
        jz      .done
3231
        jz      .done
3232
        and     edx, 31
3232
        and     edx, 31
3233
        cmp     ecx, edx
3233
        cmp     ecx, edx
3234
        jnc     .done
3234
        jnc     .done
3235
        add     esp, 8
3235
        add     esp, 8
3236
        jmp     .start
3236
        jmp     .start
3237
 
3237
 
3238
@@:
3238
@@:
3239
        sub     edi, 4
3239
        sub     edi, 4
3240
        call    bitmapBuffering
3240
        call    bitmapBuffering
3241
        push    ecx
3241
        push    ecx
3242
.small:     ; less than 32 clusters
3242
.small:     ; less than 32 clusters
3243
        pop     ecx
3243
        pop     ecx
3244
        or      eax, -1
3244
        or      eax, -1
3245
        repz scasd
3245
        repz scasd
3246
        jecxz   @b
3246
        jecxz   @b
3247
        push    ecx
3247
        push    ecx
3248
        mov     eax, [edi-4]
3248
        mov     eax, [edi-4]
3249
        not     eax
3249
        not     eax
3250
@@:
3250
@@:
3251
        bsf     ecx, eax    ; first 0
3251
        bsf     ecx, eax    ; first 0
3252
        jz      .small
3252
        jz      .small
3253
        not     eax
3253
        not     eax
3254
        shr     eax, cl
3254
        shr     eax, cl
3255
        shl     eax, cl
3255
        shl     eax, cl
3256
        bsf     edx, eax    ; next 1
3256
        bsf     edx, eax    ; next 1
3257
        jz      @f
3257
        jz      @f
3258
        sub     edx, ecx
3258
        sub     edx, ecx
3259
        cmp     edx, [ebp+NTFS.fileDataSize]
3259
        cmp     edx, [ebp+NTFS.fileDataSize]
3260
        jnc     .got        ; fits inside
3260
        jnc     .got        ; fits inside
3261
        bsf     ecx, eax
3261
        bsf     ecx, eax
3262
        not     eax
3262
        not     eax
3263
        shr     eax, cl
3263
        shr     eax, cl
3264
        shl     eax, cl
3264
        shl     eax, cl
3265
        jmp     @b
3265
        jmp     @b
3266
 
3266
 
3267
@@:         ; next dword
3267
@@:         ; next dword
3268
        mov     eax, [edi]
3268
        mov     eax, [edi]
3269
        bsf     edx, eax
3269
        bsf     edx, eax
3270
        jz      .got        ; empty
3270
        jz      .got        ; empty
3271
        add     edx, 32
3271
        add     edx, 32
3272
        sub     edx, ecx
3272
        sub     edx, ecx
3273
        cmp     edx, [ebp+NTFS.fileDataSize]
3273
        cmp     edx, [ebp+NTFS.fileDataSize]
3274
        jc      .small
3274
        jc      .small
3275
.got:
3275
.got:
3276
        sub     edi, 4
3276
        sub     edi, 4
3277
        push    ecx         ; starting bit
3277
        push    ecx         ; starting bit
3278
        push    edi         ; starting dword
3278
        push    edi         ; starting dword
3279
.done:      ; mark space
3279
.done:      ; mark space
3280
        pop     edi ecx
3280
        pop     edi ecx
3281
        cmp     ecx, 32
3281
        cmp     ecx, 32
3282
        jc      @f
3282
        jc      @f
3283
        xor     ecx, ecx
3283
        xor     ecx, ecx
3284
        add     edi, 4
3284
        add     edi, 4
3285
@@:
3285
@@:
3286
        push    ecx edi
3286
        push    ecx edi
3287
        or      eax, -1
3287
        or      eax, -1
3288
        shr     eax, cl
3288
        shr     eax, cl
3289
        shl     eax, cl
3289
        shl     eax, cl
3290
        neg     ecx
3290
        neg     ecx
3291
        add     ecx, 32
3291
        add     ecx, 32
3292
        sub     ecx, [ebp+NTFS.fileDataSize]
3292
        sub     ecx, [ebp+NTFS.fileDataSize]
3293
        jc      @f
3293
        jc      @f
3294
        shl     eax, cl     ; fits inside dword
3294
        shl     eax, cl     ; fits inside dword
3295
        shr     eax, cl
3295
        shr     eax, cl
3296
        or      [edi], eax
3296
        or      [edi], eax
3297
        jmp     .end
3297
        jmp     .end
3298
 
3298
 
3299
@@:
3299
@@:
3300
        or      [edi], eax
3300
        or      [edi], eax
3301
        neg     ecx
3301
        neg     ecx
3302
        push    ecx
3302
        push    ecx
3303
        shr     ecx, 5
3303
        shr     ecx, 5
3304
        add     edi, 4
3304
        add     edi, 4
3305
        or      eax, -1
3305
        or      eax, -1
3306
        rep stosd
3306
        rep stosd
3307
        pop     ecx
3307
        pop     ecx
3308
        and     ecx, 31
3308
        and     ecx, 31
3309
        shr     eax, cl
3309
        shr     eax, cl
3310
        shl     eax, cl
3310
        shl     eax, cl
3311
        not     eax
3311
        not     eax
3312
        or      [edi], eax
3312
        or      [edi], eax
3313
.end:
3313
.end:
3314
        pop     eax
3314
        pop     eax
3315
        pop     ecx
3315
        pop     ecx
3316
        sub     eax, [ebp+NTFS.BitmapBuffer]
3316
        sub     eax, [ebp+NTFS.BitmapBuffer]
3317
        shl     eax, 3
3317
        shl     eax, 3
3318
        add     eax, ecx
3318
        add     eax, ecx
3319
        pop     ecx
3319
        pop     ecx
3320
        mov     ecx, [ebp+NTFS.fileDataSize]
3320
        mov     ecx, [ebp+NTFS.fileDataSize]
3321
        mov     [ebp+NTFS.fileDataStart], eax
3321
        mov     [ebp+NTFS.fileDataStart], eax
3322
        add     ecx, eax
3322
        add     ecx, eax
3323
        add     ecx, 4095
3323
        add     ecx, 4095
3324
        shr     ecx, 3+9
3324
        shr     ecx, 3+9
3325
        shr     eax, 3+9
3325
        shr     eax, 3+9
3326
        sub     ecx, eax
3326
        sub     ecx, eax
3327
        mov     ebx, eax
3327
        mov     ebx, eax
3328
        shl     ebx, 9
3328
        shl     ebx, 9
3329
        add     eax, [ebp+NTFS.BitmapLocation]
3329
        add     eax, [ebp+NTFS.BitmapLocation]
3330
        add     ebx, [ebp+NTFS.BitmapBuffer]
3330
        add     ebx, [ebp+NTFS.BitmapBuffer]
3331
        xor     edx, edx
3331
        xor     edx, edx
3332
        jmp     fs_write64_app
3332
        jmp     fs_write64_app
3333
 
3333
 
3334
ntfsSpaceFree:
3334
ntfsSpaceFree:
3335
; free disk space
3335
; free disk space
3336
;   in:
3336
;   in:
3337
; edi = starting cluster
3337
; edi = starting cluster
3338
; ebx = size in clusters
3338
; ebx = size in clusters
3339
        mov     eax, edi
3339
        mov     eax, edi
3340
        add     eax, ebx
3340
        add     eax, ebx
3341
        shr     eax, 3
3341
        shr     eax, 3
3342
        cmp     eax, [ebp+NTFS.BitmapSize]
3342
        cmp     eax, [ebp+NTFS.BitmapSize]
3343
        jc      @f
3343
        jc      @f
3344
        add     eax, [ebp+NTFS.BitmapBuffer]
3344
        add     eax, [ebp+NTFS.BitmapBuffer]
3345
        push    edi
3345
        push    edi
3346
        mov     edi, eax
3346
        mov     edi, eax
3347
        call    bitmapBuffering
3347
        call    bitmapBuffering
3348
        pop     edi
3348
        pop     edi
3349
@@:
3349
@@:
3350
        push    edi
3350
        push    edi
3351
        mov     ecx, edi
3351
        mov     ecx, edi
3352
        shr     edi, 5
3352
        shr     edi, 5
3353
        shl     edi, 2
3353
        shl     edi, 2
3354
        add     edi, [ebp+NTFS.BitmapBuffer]
3354
        add     edi, [ebp+NTFS.BitmapBuffer]
3355
        and     ecx, 31
3355
        and     ecx, 31
3356
        xor     eax, eax
3356
        xor     eax, eax
3357
        dec     eax
3357
        dec     eax
3358
        shr     eax, cl
3358
        shr     eax, cl
3359
        shl     eax, cl
3359
        shl     eax, cl
3360
        neg     ecx
3360
        neg     ecx
3361
        add     ecx, 32
3361
        add     ecx, 32
3362
        sub     ecx, ebx
3362
        sub     ecx, ebx
3363
        jc      @f
3363
        jc      @f
3364
        shl     eax, cl     ; fits inside dword
3364
        shl     eax, cl     ; fits inside dword
3365
        shr     eax, cl
3365
        shr     eax, cl
3366
        not     eax
3366
        not     eax
3367
        and     [edi], eax
3367
        and     [edi], eax
3368
        jmp     .writeBitmap
3368
        jmp     .writeBitmap
3369
 
3369
 
3370
@@:
3370
@@:
3371
        not     eax
3371
        not     eax
3372
        and     [edi], eax
3372
        and     [edi], eax
3373
        neg     ecx
3373
        neg     ecx
3374
        push    ecx
3374
        push    ecx
3375
        shr     ecx, 5
3375
        shr     ecx, 5
3376
        add     edi, 4
3376
        add     edi, 4
3377
        xor     eax, eax
3377
        xor     eax, eax
3378
        rep stosd
3378
        rep stosd
3379
        pop     ecx
3379
        pop     ecx
3380
        and     ecx, 31
3380
        and     ecx, 31
3381
        dec     eax
3381
        dec     eax
3382
        shr     eax, cl
3382
        shr     eax, cl
3383
        shl     eax, cl
3383
        shl     eax, cl
3384
        and     [edi], eax
3384
        and     [edi], eax
3385
.writeBitmap:
3385
.writeBitmap:
3386
        pop     eax
3386
        pop     eax
3387
        mov     edi, eax
3387
        mov     edi, eax
3388
        lea     ecx, [eax+ebx+4095]
3388
        lea     ecx, [eax+ebx+4095]
3389
        shr     eax, 3+9
3389
        shr     eax, 3+9
3390
        shr     ecx, 3+9
3390
        shr     ecx, 3+9
3391
        sub     ecx, eax
3391
        sub     ecx, eax
3392
        mov     ebx, eax
3392
        mov     ebx, eax
3393
        shl     ebx, 9
3393
        shl     ebx, 9
3394
        add     eax, [ebp+NTFS.BitmapLocation]
3394
        add     eax, [ebp+NTFS.BitmapLocation]
3395
        add     ebx, [ebp+NTFS.BitmapBuffer]
3395
        add     ebx, [ebp+NTFS.BitmapBuffer]
3396
        xor     edx, edx
3396
        xor     edx, edx
3397
        jmp     fs_write64_app
3397
        jmp     fs_write64_app
3398
 
3398
 
3399
bitmapBuffering:
3399
bitmapBuffering:
3400
; Extend BitmapBuffer and read next 32kb of bitmap
3400
; Extend BitmapBuffer and read next 32kb of bitmap
3401
; Warning: $Bitmap fragmentation is not foreseen
3401
; Warning: $Bitmap fragmentation is not foreseen
3402
; in: edi -> position in bitmap buffer
3402
; in: edi -> position in bitmap buffer
3403
; out: ecx = number of buffered dwords left
3403
; out: ecx = number of buffered dwords left
3404
        push    ebx
3404
        push    ebx
3405
        mov     eax, [ebp+NTFS.BitmapTotalSize]
3405
        mov     eax, [ebp+NTFS.BitmapTotalSize]
3406
        cmp     eax, [ebp+NTFS.BitmapSize]
3406
        cmp     eax, [ebp+NTFS.BitmapSize]
3407
        jz      .end
3407
        jz      .end
3408
        stdcall alloc_pages, 8
3408
        stdcall alloc_pages, 8
3409
        test    eax, eax
3409
        test    eax, eax
3410
        jz      .end
3410
        jz      .end
3411
        add     eax, 3
3411
        add     eax, 3
3412
        mov     ebx, [ebp+NTFS.BitmapBuffer]
3412
        mov     ebx, [ebp+NTFS.BitmapBuffer]
3413
        add     ebx, [ebp+NTFS.BitmapSize]
3413
        add     ebx, [ebp+NTFS.BitmapSize]
3414
        push    ebx
3414
        push    ebx
3415
        mov     ecx, 8
3415
        mov     ecx, 8
3416
        call    commit_pages
3416
        call    commit_pages
3417
        mov     eax, [ebp+NTFS.BitmapSize]
3417
        mov     eax, [ebp+NTFS.BitmapSize]
3418
        shr     eax, 9
3418
        shr     eax, 9
3419
        add     eax, [ebp+NTFS.BitmapLocation]
3419
        add     eax, [ebp+NTFS.BitmapLocation]
3420
        pop     ebx
3420
        pop     ebx
3421
        mov     ecx, 64
3421
        mov     ecx, 64
3422
        xor     edx, edx
3422
        xor     edx, edx
3423
        call    fs_read64_app
3423
        call    fs_read64_app
3424
        test    eax, eax
3424
        test    eax, eax
3425
        jnz     .err
3425
        jnz     .err
3426
        mov     eax, [ebp+NTFS.BitmapSize]
3426
        mov     eax, [ebp+NTFS.BitmapSize]
3427
        add     eax, 8000h
3427
        add     eax, 8000h
3428
        cmp     [ebp+NTFS.BitmapTotalSize], eax
3428
        cmp     [ebp+NTFS.BitmapTotalSize], eax
3429
        jnc     @f
3429
        jnc     @f
3430
        mov     eax, [ebp+NTFS.BitmapTotalSize]
3430
        mov     eax, [ebp+NTFS.BitmapTotalSize]
3431
@@:
3431
@@:
3432
        mov     [ebp+NTFS.BitmapSize], eax
3432
        mov     [ebp+NTFS.BitmapSize], eax
3433
        pop     ebx
3433
        pop     ebx
3434
        mov     ecx, [ebp+NTFS.BitmapBuffer]
3434
        mov     ecx, [ebp+NTFS.BitmapBuffer]
3435
        add     ecx, eax
3435
        add     ecx, eax
3436
        sub     ecx, edi
3436
        sub     ecx, edi
3437
        jbe     bitmapBuffering
3437
        jbe     bitmapBuffering
3438
        shr     ecx, 2
3438
        shr     ecx, 2
3439
        ret
3439
        ret
3440
 
3440
 
3441
.err:
3441
.err:
3442
        mov     eax, [ebp+NTFS.BitmapBuffer]
3442
        mov     eax, [ebp+NTFS.BitmapBuffer]
3443
        add     eax, [ebp+NTFS.BitmapSize]
3443
        add     eax, [ebp+NTFS.BitmapSize]
3444
        mov     ecx, 8
3444
        mov     ecx, 8
3445
        call    release_pages
3445
        call    release_pages
3446
.end:
3446
.end:
3447
        add     esp, 12     ; ret
3447
        add     esp, 12     ; ret
3448
        stc
3448
        stc
3449
        ret
3449
        ret
3450
 
3450
 
3451
;----------------------------------------------------------------
3451
;----------------------------------------------------------------
3452
ntfs_WriteFile:
3452
ntfs_WriteFile:
3453
        call    ntfs_lock
3453
        call    ntfs_lock
3454
        call    ntfs_find_lfn
3454
        call    ntfs_find_lfn
3455
        jc      ntfsNotFound
3455
        jc      ntfsNotFound
3456
        cmp     [ebp+NTFS.cur_iRecord], 16
3456
        cmp     [ebp+NTFS.cur_iRecord], 16
3457
        jc      ntfsDenied
3457
        jc      ntfsDenied
3458
        test    dword [eax+fileFlags], 10000001h
3458
        test    dword [eax+fileFlags], 10000001h
3459
        jnz     ntfsDenied
3459
        jnz     ntfsDenied
3460
        cmp     [ebp+NTFS.fragmentCount], 1
3460
        cmp     [ebp+NTFS.fragmentCount], 1
3461
        jnz     ntfsUnsupported     ; record fragmented
3461
        jnz     ntfsUnsupported     ; record fragmented
3462
; edit directory node
3462
; edit directory node
3463
        mov     edi, [ebp+NTFS.cur_index_buf]
3463
        mov     edi, [ebp+NTFS.cur_index_buf]
3464
        cmp     dword [edi], 'INDX'
3464
        cmp     dword [edi], 'INDX'
3465
        jz      @f
3465
        jz      @f
3466
        mov     esi, [ebp+NTFS.frs_buffer]
3466
        mov     esi, [ebp+NTFS.frs_buffer]
3467
        mov     ecx, [esi+recordRealSize]
3467
        mov     ecx, [esi+recordRealSize]
3468
        shr     ecx, 2
3468
        shr     ecx, 2
3469
        rep movsd
3469
        rep movsd
3470
        mov     esi, [ebp+NTFS.attr_offs]
3470
        mov     esi, [ebp+NTFS.attr_offs]
3471
        mov     cl, [esi+attributeOffset]
3471
        mov     cl, [esi+attributeOffset]
3472
        sub     esi, [ebp+NTFS.frs_buffer]
3472
        sub     esi, [ebp+NTFS.frs_buffer]
3473
        add     eax, ecx
3473
        add     eax, ecx
3474
        add     eax, esi
3474
        add     eax, esi
3475
@@:
3475
@@:
3476
        mov     edi, eax
3476
        mov     edi, eax
3477
        mov     eax, [ebx+4]
3477
        mov     eax, [ebx+4]
3478
        mov     edx, [ebx+8]
3478
        mov     edx, [ebx+8]
3479
        add     eax, [ebx+12]
3479
        add     eax, [ebx+12]
3480
        adc     edx, 0
3480
        adc     edx, 0
3481
        mov     [edi+fileRealSize], eax
3481
        mov     [edi+fileRealSize], eax
-
 
3482
        cmp     edx, [edi+fileRealSize+4]
-
 
3483
        jc      @f
-
 
3484
        jnz     .resize
-
 
3485
        cmp     [edi+fileRealSize], eax
-
 
3486
        jnc     @f
-
 
3487
.resize:
-
 
3488
        mov     [edi+fileRealSize], eax
-
 
3489
        mov     [edi+fileRealSize+4], edx
-
 
3490
@@:
3482
        mov     [edi+fileRealSize+4], edx
3491
        mov     [edi+fileRealSize+4], edx
3483
        push    edx eax ebx
3492
        push    edx eax ebx
3484
        call    ntfsGetTime
3493
        call    ntfsGetTime
3485
        mov     [edi+fileModified], eax
3494
        mov     [edi+fileModified], eax
3486
        mov     [edi+fileModified+4], edx
3495
        mov     [edi+fileModified+4], edx
3487
        mov     [edi+recordModified], eax
3496
        mov     [edi+recordModified], eax
3488
        mov     [edi+recordModified+4], edx
3497
        mov     [edi+recordModified+4], edx
3489
        mov     [edi+fileAccessed], eax
3498
        mov     [edi+fileAccessed], eax
3490
        mov     [edi+fileAccessed+4], edx
3499
        mov     [edi+fileAccessed+4], edx
3491
        pop     ebx ecx edx
3500
        pop     ebx ecx edx
3492
        mov     eax, [ebp+NTFS.LastRead]
3501
        mov     eax, [ebp+NTFS.LastRead]
3493
        mov     [ebp+NTFS.nodeLastRead], eax
3502
        mov     [ebp+NTFS.nodeLastRead], eax
3494
        mov     [ebp+NTFS.cur_attr], 0x80
3503
        mov     [ebp+NTFS.cur_attr], 0x80
3495
        mov     [ebp+NTFS.cur_offs], 0
3504
        mov     [ebp+NTFS.cur_offs], 0
3496
        mov     [ebp+NTFS.cur_size], 0
3505
        mov     [ebp+NTFS.cur_size], 0
3497
        call    ntfs_read_attr
3506
        call    ntfs_read_attr
3498
        jc      ntfsFail
3507
        jc      ntfsFail
3499
        mov     esi, edi
3508
        mov     esi, edi
3500
        mov     edi, [ebp+NTFS.frs_buffer]
3509
        mov     edi, [ebp+NTFS.frs_buffer]
3501
        cmp     word [edi+baseRecordReuse], 0
3510
        cmp     word [edi+baseRecordReuse], 0
3502
        jnz     ntfsUnsupported     ; auxiliary record
3511
        jnz     ntfsUnsupported     ; auxiliary record
3503
        mov     al, [edi+attributeOffset]
3512
        mov     al, [edi+attributeOffset]
3504
        add     edi, eax
3513
        add     edi, eax
3505
        mov     al, [edi+attributeOffset]
3514
        mov     al, [edi+attributeOffset]
3506
        add     edi, eax
3515
        add     edi, eax
3507
        mov     eax, ecx
3516
        mov     eax, ecx
3508
        mov     ecx, 6
3517
        mov     ecx, 6
3509
        add     esi, fileModified
3518
        add     esi, fileModified
3510
        add     edi, 8
3519
        add     edi, 8
3511
        rep movsd
3520
        rep movsd
3512
        mov     ecx, [ebp+NTFS.attr_offs]
3521
        mov     ecx, [ebp+NTFS.attr_offs]
3513
        cmp     word [ecx+attributeFlags], 0
3522
        cmp     word [ecx+attributeFlags], 0
3514
        jnz     ntfsUnsupported
3523
        jnz     ntfsUnsupported
3515
        push    ebx
3524
        push    ebx
3516
        cmp     byte [ecx+nonResidentFlag], 0
3525
        cmp     byte [ecx+nonResidentFlag], 0
3517
        jz      .resizeAttribute
3526
        jz      .resizeAttribute
3518
        cmp     edx, [ecx+attributeRealSize+4]
3527
        cmp     edx, [ecx+attributeRealSize+4]
3519
        jc      .writeNode
3528
        jc      .writeNode
3520
        jnz     .resizeAttribute
3529
        jnz     .resizeAttribute
3521
        cmp     [ecx+attributeRealSize], eax
3530
        cmp     [ecx+attributeRealSize], eax
3522
        jnc     .writeNode
3531
        jnc     .writeNode
3523
.resizeAttribute:
3532
.resizeAttribute:
3524
        call    resizeAttribute
3533
        call    resizeAttribute
3525
        jc      ntfsErrorPop
3534
        jc      ntfsErrorPop
3526
        mov     ecx, [ebp+NTFS.attr_offs]
3535
        mov     ecx, [ebp+NTFS.attr_offs]
3527
        cmp     byte [ecx+nonResidentFlag], 1
3536
        cmp     byte [ecx+nonResidentFlag], 1
3528
        jz      @f
3537
        jz      @f
3529
        mov     ebx, [esp]
3538
        mov     ebx, [esp]
3530
        movzx   edi, byte [ecx+attributeOffset]
3539
        movzx   edi, byte [ecx+attributeOffset]
3531
        add     edi, ecx
3540
        add     edi, ecx
3532
        add     edi, [ebx+4]
3541
        add     edi, [ebx+4]
3533
        mov     ecx, [ebx+12]
3542
        mov     ecx, [ebx+12]
3534
        mov     esi, [ebx+16]
3543
        mov     esi, [ebx+16]
3535
        rep movsb
3544
        rep movsb
3536
@@:
3545
@@:
3537
        mov     ebx, [ebp+NTFS.frs_buffer]
3546
        mov     ebx, [ebp+NTFS.frs_buffer]
3538
        mov     edx, [ebp+NTFS.mftLastRead]
3547
        mov     edx, [ebp+NTFS.mftLastRead]
3539
        call    writeRecord     ; file
3548
        call    writeRecord     ; file
3540
        call    ntfs_restore_usa_frs
3549
        call    ntfs_restore_usa_frs
3541
.writeNode:
3550
.writeNode:
3542
        mov     ebx, [ebp+NTFS.cur_index_buf]
3551
        mov     ebx, [ebp+NTFS.cur_index_buf]
3543
        mov     edx, [ebp+NTFS.nodeLastRead]
3552
        mov     edx, [ebp+NTFS.nodeLastRead]
3544
        call    writeRecord     ; directory
3553
        call    writeRecord     ; directory
3545
        pop     ebx
3554
        pop     ebx
3546
        mov     ecx, [ebp+NTFS.attr_offs]
3555
        mov     ecx, [ebp+NTFS.attr_offs]
3547
        cmp     byte [ecx+nonResidentFlag], 0
3556
        cmp     byte [ecx+nonResidentFlag], 0
3548
        jz      .done
3557
        jz      .done
3549
        mov     ecx, [ebx+12]
3558
        mov     ecx, [ebx+12]
3550
        test    ecx, ecx
3559
        test    ecx, ecx
3551
        jz      .done
3560
        jz      .done
3552
        mov     eax, [ebx+4]
3561
        mov     eax, [ebx+4]
3553
        mov     edx, [ebx+8]
3562
        mov     edx, [ebx+8]
3554
        mov     esi, [ebx+16]
3563
        mov     esi, [ebx+16]
3555
        shrd    eax, edx, 9
3564
        shrd    eax, edx, 9
3556
        test    dword[ebx+4], 1FFh
3565
        test    dword[ebx+4], 1FFh
3557
        jz      .aligned
3566
        jz      .aligned
3558
        mov     [ebp+NTFS.cur_offs], eax
3567
        mov     [ebp+NTFS.cur_offs], eax
3559
        mov     [ebp+NTFS.cur_size], 1
3568
        mov     [ebp+NTFS.cur_size], 1
3560
        lea     edi, [ebp+NTFS.bitmap_buf]
3569
        lea     edi, [ebp+NTFS.bitmap_buf]
3561
        mov     [ebp+NTFS.cur_buf], edi
3570
        mov     [ebp+NTFS.cur_buf], edi
3562
        call    ntfs_read_attr.continue
3571
        call    ntfs_read_attr.continue
3563
        jc      ntfsDevice
3572
        jc      ntfsDevice
3564
        mov     eax, [ebx+4]
3573
        mov     eax, [ebx+4]
3565
        and     eax, 1FFh
3574
        and     eax, 1FFh
3566
        add     edi, eax
3575
        add     edi, eax
3567
        sub     eax, [ebp+NTFS.cur_read]
3576
        sub     eax, [ebp+NTFS.cur_read]
3568
        neg     eax
3577
        neg     eax
3569
        push    ecx
3578
        push    ecx
3570
        cmp     ecx, eax
3579
        cmp     ecx, eax
3571
        jb      @f
3580
        jb      @f
3572
        mov     ecx, eax
3581
        mov     ecx, eax
3573
@@:
3582
@@:
3574
        sub     [esp], ecx
3583
        sub     [esp], ecx
3575
        rep movsb
3584
        rep movsb
3576
        push    ebx
3585
        push    ebx
3577
        mov     eax, [ebp+NTFS.LastRead]
3586
        mov     eax, [ebp+NTFS.LastRead]
3578
        lea     ebx, [ebp+NTFS.bitmap_buf]
3587
        lea     ebx, [ebp+NTFS.bitmap_buf]
3579
        mov     ecx, 1
3588
        mov     ecx, 1
3580
        xor     edx, edx
3589
        xor     edx, edx
3581
        call    fs_write64_app
3590
        call    fs_write64_app
3582
        pop     ebx
3591
        pop     ebx
3583
        pop     ecx
3592
        pop     ecx
3584
        test    ecx, ecx
3593
        test    ecx, ecx
3585
        jz      .done
3594
        jz      .done
3586
        mov     eax, [ebx+4]
3595
        mov     eax, [ebx+4]
3587
        mov     edx, [ebx+8]
3596
        mov     edx, [ebx+8]
3588
        shrd    eax, edx, 9
3597
        shrd    eax, edx, 9
3589
        inc     eax
3598
        inc     eax
3590
.aligned:
3599
.aligned:
3591
        push    ecx
3600
        push    ecx
3592
        shr     ecx, 9
3601
        shr     ecx, 9
3593
        mov     [ebp+NTFS.cur_offs], eax
3602
        mov     [ebp+NTFS.cur_offs], eax
3594
        mov     [ebp+NTFS.cur_size], ecx
3603
        mov     [ebp+NTFS.cur_size], ecx
3595
        mov     [ebp+NTFS.cur_buf], esi
3604
        mov     [ebp+NTFS.cur_buf], esi
3596
        add     eax, ecx
3605
        add     eax, ecx
3597
        push    eax
3606
        push    eax
3598
        mov     [ebp+NTFS.bWriteAttr], 1
3607
        mov     [ebp+NTFS.bWriteAttr], 1
3599
        call    ntfs_read_attr.continue
3608
        call    ntfs_read_attr.continue
3600
        mov     [ebp+NTFS.bWriteAttr], 0
3609
        mov     [ebp+NTFS.bWriteAttr], 0
3601
        pop     [ebp+NTFS.cur_offs]
3610
        pop     [ebp+NTFS.cur_offs]
3602
        pop     ecx
3611
        pop     ecx
3603
        jc      ntfsDevice
3612
        jc      ntfsDevice
3604
        and     ecx, 1FFh
3613
        and     ecx, 1FFh
3605
        jz      .done
3614
        jz      .done
3606
        add     esi, [ebp+NTFS.cur_read]
3615
        add     esi, [ebp+NTFS.cur_read]
3607
        mov     [ebp+NTFS.cur_size], 1
3616
        mov     [ebp+NTFS.cur_size], 1
3608
        lea     edi, [ebp+NTFS.bitmap_buf]
3617
        lea     edi, [ebp+NTFS.bitmap_buf]
3609
        mov     [ebp+NTFS.cur_buf], edi
3618
        mov     [ebp+NTFS.cur_buf], edi
3610
        call    ntfs_read_attr.continue
3619
        call    ntfs_read_attr.continue
3611
        jc      ntfsDevice
3620
        jc      ntfsDevice
3612
        rep movsb
3621
        rep movsb
3613
        push    ebx
3622
        push    ebx
3614
        mov     eax, [ebp+NTFS.LastRead]
3623
        mov     eax, [ebp+NTFS.LastRead]
3615
        lea     ebx, [ebp+NTFS.bitmap_buf]
3624
        lea     ebx, [ebp+NTFS.bitmap_buf]
3616
        mov     ecx, 1
3625
        mov     ecx, 1
3617
        xor     edx, edx
3626
        xor     edx, edx
3618
        call    fs_write64_app
3627
        call    fs_write64_app
3619
        pop     ebx
3628
        pop     ebx
3620
.done:
3629
.done:
3621
        mov     ebx, [ebx+12]
3630
        mov     ebx, [ebx+12]
3622
        jmp     ntfsDone
3631
        jmp     ntfsDone
3623
 
3632
 
3624
;----------------------------------------------------------------
3633
;----------------------------------------------------------------
3625
ntfs_Delete:
3634
ntfs_Delete:
3626
        call    ntfs_lock
3635
        call    ntfs_lock
3627
        call    ntfs_find_lfn
3636
        call    ntfs_find_lfn
3628
        jc      ntfsNotFound
3637
        jc      ntfsNotFound
3629
        cmp     [ebp+NTFS.cur_iRecord], 16
3638
        cmp     [ebp+NTFS.cur_iRecord], 16
3630
        jc      ntfsDenied
3639
        jc      ntfsDenied
3631
        test    byte [eax+fileFlags], 1
3640
        test    byte [eax+fileFlags], 1
3632
        jnz     ntfsDenied
3641
        jnz     ntfsDenied
3633
        cmp     [ebp+NTFS.fragmentCount], 1
3642
        cmp     [ebp+NTFS.fragmentCount], 1
3634
        jnz     ntfsUnsupported     ; record fragmented
3643
        jnz     ntfsUnsupported     ; record fragmented
3635
        mov     ebx, [eax+directoryRecordReference]
3644
        mov     ebx, [eax+directoryRecordReference]
3636
        mov     [ebp+NTFS.newRecord], ebx
3645
        mov     [ebp+NTFS.newRecord], ebx
3637
        mov     bx, [eax+fileReferenceReuse]
3646
        mov     bx, [eax+fileReferenceReuse]
3638
        mov     [ebp+NTFS.indexPointer], esi
3647
        mov     [ebp+NTFS.indexPointer], esi
3639
        mov     eax, [ebp+NTFS.cur_iRecord]
3648
        mov     eax, [ebp+NTFS.cur_iRecord]
3640
        shr     eax, 3
3649
        shr     eax, 3
3641
        cmp     eax, [ebp+NTFS.mftBitmapSize]
3650
        cmp     eax, [ebp+NTFS.mftBitmapSize]
3642
        jnc     ntfsUnsupported
3651
        jnc     ntfsUnsupported
3643
; examine file record
3652
; examine file record
3644
        mov     [ebp+NTFS.cur_attr], 0x80   ; file?
3653
        mov     [ebp+NTFS.cur_attr], 0x80   ; file?
3645
        mov     [ebp+NTFS.cur_offs], 0
3654
        mov     [ebp+NTFS.cur_offs], 0
3646
        mov     [ebp+NTFS.cur_size], 0
3655
        mov     [ebp+NTFS.cur_size], 0
3647
        call    ntfs_read_attr
3656
        call    ntfs_read_attr
3648
        jnc     @f
3657
        jnc     @f
3649
        xor     eax, eax
3658
        xor     eax, eax
3650
        push    ebx eax eax eax eax
3659
        push    ebx eax eax eax eax
3651
        mov     [esp+12], esp
3660
        mov     [esp+12], esp
3652
        push    eax
3661
        push    eax
3653
        mov     ebx, esp
3662
        mov     ebx, esp
3654
        mov     [ebp+NTFS.cur_attr], 0x90   ; folder?
3663
        mov     [ebp+NTFS.cur_attr], 0x90   ; folder?
3655
        call    ntfs_ReadFolder.doit
3664
        call    ntfs_ReadFolder.doit
3656
        mov     edx, [esp+12]
3665
        mov     edx, [esp+12]
3657
        add     esp, 20
3666
        add     esp, 20
3658
        pop     ebx
3667
        pop     ebx
3659
        test    eax, eax
3668
        test    eax, eax
3660
        jnz     .ret
3669
        jnz     .ret
3661
        cmp     edx, 2
3670
        cmp     edx, 2
3662
        jnz     ntfsDenied      ; folder is not empty
3671
        jnz     ntfsDenied      ; folder is not empty
3663
        mov     [ebp+NTFS.cur_attr], 0xA0
3672
        mov     [ebp+NTFS.cur_attr], 0xA0
3664
        mov     [ebp+NTFS.cur_offs], 0
3673
        mov     [ebp+NTFS.cur_offs], 0
3665
        mov     [ebp+NTFS.cur_size], 0
3674
        mov     [ebp+NTFS.cur_size], 0
3666
        call    ntfs_read_attr.newAttribute
3675
        call    ntfs_read_attr.newAttribute
3667
        jc      .deleteFileRecord
3676
        jc      .deleteFileRecord
3668
@@:
3677
@@:
3669
        mov     esi, [ebp+NTFS.frs_buffer]
3678
        mov     esi, [ebp+NTFS.frs_buffer]
3670
        cmp     word [esi+baseRecordReuse], 0
3679
        cmp     word [esi+baseRecordReuse], 0
3671
        jnz     ntfsUnsupported     ; auxiliary record
3680
        jnz     ntfsUnsupported     ; auxiliary record
3672
        cmp     word [esi+reuseCounter], bx
3681
        cmp     word [esi+reuseCounter], bx
3673
        jnz     .backToIndex        ; broken index
3682
        jnz     .backToIndex        ; broken index
3674
        test    byte [esi+recordFlags], 1
3683
        test    byte [esi+recordFlags], 1
3675
        jz      .writeBitmapMFT     ; record deleted
3684
        jz      .writeBitmapMFT     ; record deleted
3676
        cmp     byte [esi+hardLinkCounter], 3
3685
        cmp     byte [esi+hardLinkCounter], 3
3677
        jnc     ntfsUnsupported
3686
        jnc     ntfsUnsupported
3678
        mov     esi, [ebp+NTFS.attr_offs]
3687
        mov     esi, [ebp+NTFS.attr_offs]
3679
        cmp     byte [esi+nonResidentFlag], 0
3688
        cmp     byte [esi+nonResidentFlag], 0
3680
        jz      .deleteFileRecord
3689
        jz      .deleteFileRecord
3681
        movzx   eax, byte [esi+dataRunsOffset]
3690
        movzx   eax, byte [esi+dataRunsOffset]
3682
        add     esi, eax
3691
        add     esi, eax
3683
        xor     edi, edi
3692
        xor     edi, edi
3684
        sub     esp, 16
3693
        sub     esp, 16
3685
@@:
3694
@@:
3686
        call    ntfs_decode_mcb_entry
3695
        call    ntfs_decode_mcb_entry
3687
        jnc     @f
3696
        jnc     @f
3688
        cmp     dword[esp+8], 0
3697
        cmp     dword[esp+8], 0
3689
        jz      @b
3698
        jz      @b
3690
        add     edi, [esp+8]
3699
        add     edi, [esp+8]
3691
        mov     ebx, [esp]
3700
        mov     ebx, [esp]
3692
        call    ntfsSpaceFree
3701
        call    ntfsSpaceFree
3693
        jnc     @b
3702
        jnc     @b
3694
@@:
3703
@@:
3695
        add     esp, 16
3704
        add     esp, 16
3696
.deleteFileRecord:
3705
.deleteFileRecord:
3697
        mov     ebx, [ebp+NTFS.frs_buffer]
3706
        mov     ebx, [ebp+NTFS.frs_buffer]
3698
        mov     byte [ebx+recordFlags], 0
3707
        mov     byte [ebx+recordFlags], 0
3699
        mov     edx, [ebp+NTFS.mftLastRead]
3708
        mov     edx, [ebp+NTFS.mftLastRead]
3700
        call    writeRecord
3709
        call    writeRecord
3701
.writeBitmapMFT:
3710
.writeBitmapMFT:
3702
        mov     eax, [ebp+NTFS.cur_iRecord]
3711
        mov     eax, [ebp+NTFS.cur_iRecord]
3703
        mov     ecx, eax
3712
        mov     ecx, eax
3704
        shr     eax, 3
3713
        shr     eax, 3
3705
        and     ecx, 7
3714
        and     ecx, 7
3706
        mov     edi, [ebp+NTFS.mftBitmapBuffer]
3715
        mov     edi, [ebp+NTFS.mftBitmapBuffer]
3707
        btr     [edi+eax], ecx
3716
        btr     [edi+eax], ecx
3708
        shr     eax, 9
3717
        shr     eax, 9
3709
        mov     ebx, eax
3718
        mov     ebx, eax
3710
        shl     ebx, 9
3719
        shl     ebx, 9
3711
        add     eax, [ebp+NTFS.mftBitmapLocation]
3720
        add     eax, [ebp+NTFS.mftBitmapLocation]
3712
        add     ebx, edi
3721
        add     ebx, edi
3713
        mov     ecx, 1
3722
        mov     ecx, 1
3714
        xor     edx, edx
3723
        xor     edx, edx
3715
        call    fs_write64_sys
3724
        call    fs_write64_sys
3716
.backToIndex:
3725
.backToIndex:
3717
        mov     eax, [ebp+NTFS.newRecord]
3726
        mov     eax, [ebp+NTFS.newRecord]
3718
        mov     [ebp+NTFS.cur_iRecord], eax
3727
        mov     [ebp+NTFS.cur_iRecord], eax
3719
        mov     esi, [ebp+NTFS.indexPointer]
3728
        mov     esi, [ebp+NTFS.indexPointer]
3720
        call    ntfs_find_lfn.doit2
3729
        call    ntfs_find_lfn.doit2
3721
        jc      ntfsFail
3730
        jc      ntfsFail
3722
        mov     ebx, [ebp+NTFS.secondIndexBuffer]
3731
        mov     ebx, [ebp+NTFS.secondIndexBuffer]
3723
        mov     byte [ebx], 0
3732
        mov     byte [ebx], 0
3724
        mov     ebx, [ebp+NTFS.LastRead]
3733
        mov     ebx, [ebp+NTFS.LastRead]
3725
        mov     [ebp+NTFS.nodeLastRead], ebx
3734
        mov     [ebp+NTFS.nodeLastRead], ebx
3726
        xor     ebx, ebx
3735
        xor     ebx, ebx
3727
        test    byte [eax+indexFlags], 1
3736
        test    byte [eax+indexFlags], 1
3728
        jz      .deleteIndex    ; no subnode
3737
        jz      .deleteIndex    ; no subnode
3729
        mov     edi, eax
3738
        mov     edi, eax
3730
        call    .findSubindex
3739
        call    .findSubindex
3731
        jc      ntfsFail
3740
        jc      ntfsFail
3732
        movzx   edx, word [edi+indexAllocatedSize]
3741
        movzx   edx, word [edi+indexAllocatedSize]
3733
        test    esi, esi
3742
        test    esi, esi
3734
        jz      @f
3743
        jz      @f
3735
        sub     edx, eax
3744
        sub     edx, eax
3736
        sub     edx, 8
3745
        sub     edx, 8
3737
@@:
3746
@@:
3738
        mov     eax, edi
3747
        mov     eax, edi
3739
        mov     ebx, esi
3748
        mov     ebx, esi
3740
        jmp     @f
3749
        jmp     @f
3741
 
3750
 
3742
.deleteIndex:
3751
.deleteIndex:
3743
        movzx   edx, word [eax+indexAllocatedSize]
3752
        movzx   edx, word [eax+indexAllocatedSize]
3744
        mov     ecx, [eax+fileRecordReference]
3753
        mov     ecx, [eax+fileRecordReference]
3745
        cmp     [eax+edx+fileRecordReference], ecx
3754
        cmp     [eax+edx+fileRecordReference], ecx
3746
        jnz     @f
3755
        jnz     @f
3747
        add     dx, [eax+edx+indexAllocatedSize]
3756
        add     dx, [eax+edx+indexAllocatedSize]
3748
@@:
3757
@@:
3749
        mov     edi, [ebp+NTFS.cur_index_buf]
3758
        mov     edi, [ebp+NTFS.cur_index_buf]
3750
        cmp     dword [edi], 'INDX'
3759
        cmp     dword [edi], 'INDX'
3751
        jz      .indexRecord
3760
        jz      .indexRecord
3752
        sub     eax, edi
3761
        sub     eax, edi
3753
        mov     edi, [ebp+NTFS.indexRoot]
3762
        mov     edi, [ebp+NTFS.indexRoot]
3754
        sub     [edi+sizeWithHeader], edx
3763
        sub     [edi+sizeWithHeader], edx
3755
        sub     [edi+sizeWithoutHeader], edx
3764
        sub     [edi+sizeWithoutHeader], edx
3756
        movzx   ecx, byte [edi+attributeOffset]
3765
        movzx   ecx, byte [edi+attributeOffset]
3757
        add     edi, ecx
3766
        add     edi, ecx
3758
        add     eax, edi
3767
        add     eax, edi
3759
        sub     [edi+rootNode+nodeRealSize], edx
3768
        sub     [edi+rootNode+nodeRealSize], edx
3760
        sub     [edi+rootNode+nodeAllocatedSize], edx
3769
        sub     [edi+rootNode+nodeAllocatedSize], edx
3761
        mov     edi, [ebp+NTFS.frs_buffer]
3770
        mov     edi, [ebp+NTFS.frs_buffer]
3762
        sub     [edi+recordRealSize], edx
3771
        sub     [edi+recordRealSize], edx
3763
        mov     ecx, [edi+recordRealSize]
3772
        mov     ecx, [edi+recordRealSize]
3764
        cmp     [edi+recordAllocatedSize], ecx
3773
        cmp     [edi+recordAllocatedSize], ecx
3765
        jmp     @f
3774
        jmp     @f
3766
 
3775
 
3767
.indexRecord:
3776
.indexRecord:
3768
        add     edi, recordNode
3777
        add     edi, recordNode
3769
        sub     [edi+nodeRealSize], edx
3778
        sub     [edi+nodeRealSize], edx
3770
        mov     ecx, [edi+nodeRealSize]
3779
        mov     ecx, [edi+nodeRealSize]
3771
        cmp     [edi+nodeAllocatedSize], ecx
3780
        cmp     [edi+nodeAllocatedSize], ecx
3772
@@:
3781
@@:
3773
        jc      ntfsUnsupported
3782
        jc      ntfsUnsupported
3774
        add     ecx, edi
3783
        add     ecx, edi
3775
        sub     ecx, eax
3784
        sub     ecx, eax
3776
        mov     esi, eax
3785
        mov     esi, eax
3777
        add     esi, edx
3786
        add     esi, edx
3778
        mov     edi, eax
3787
        mov     edi, eax
3779
        test    edx, edx
3788
        test    edx, edx
3780
        jns     @f
3789
        jns     @f
3781
        neg     edx
3790
        neg     edx
3782
        add     edx, ecx
3791
        add     edx, ecx
3783
        sub     edx, 4
3792
        sub     edx, 4
3784
        add     esi, edx
3793
        add     esi, edx
3785
        add     edi, edx
3794
        add     edi, edx
3786
        std
3795
        std
3787
@@:
3796
@@:
3788
        jz      @f
3797
        jz      @f
3789
        shr     ecx, 2
3798
        shr     ecx, 2
3790
        rep movsd
3799
        rep movsd
3791
        cld
3800
        cld
3792
@@:
3801
@@:
3793
        test    ebx, ebx
3802
        test    ebx, ebx
3794
        jz      .done
3803
        jz      .done
3795
; copy index from the subnode to replace deleted pointing index
3804
; copy index from the subnode to replace deleted pointing index
3796
        movzx   ecx, word [ebx+indexAllocatedSize]
3805
        movzx   ecx, word [ebx+indexAllocatedSize]
3797
        mov     edx, ecx
3806
        mov     edx, ecx
3798
        test    byte [ebx+indexFlags], 1
3807
        test    byte [ebx+indexFlags], 1
3799
        jz      @f
3808
        jz      @f
3800
        sub     ecx, 8
3809
        sub     ecx, 8
3801
        movzx   edi, word [ebx+edx+indexAllocatedSize]
3810
        movzx   edi, word [ebx+edx+indexAllocatedSize]
3802
        add     edi, edx
3811
        add     edi, edx
3803
        mov     esi, [ebx+ecx]
3812
        mov     esi, [ebx+ecx]
3804
        mov     [ebx+edi-8], esi
3813
        mov     [ebx+edi-8], esi
3805
        mov     [ebx+indexAllocatedSize], cx
3814
        mov     [ebx+indexAllocatedSize], cx
3806
@@:
3815
@@:
3807
        shr     ecx, 2
3816
        shr     ecx, 2
3808
        mov     esi, ebx
3817
        mov     esi, ebx
3809
        mov     edi, eax
3818
        mov     edi, eax
3810
        rep movsd
3819
        rep movsd
3811
        add     word [eax+indexAllocatedSize], 8
3820
        add     word [eax+indexAllocatedSize], 8
3812
        mov     byte [eax+indexFlags], 1
3821
        mov     byte [eax+indexFlags], 1
3813
        mov     edi, [ebp+NTFS.secondIndexBuffer]
3822
        mov     edi, [ebp+NTFS.secondIndexBuffer]
3814
        mov     eax, ebx
3823
        mov     eax, ebx
3815
        xor     ebx, ebx
3824
        xor     ebx, ebx
3816
        jmp     .indexRecord
3825
        jmp     .indexRecord
3817
 
3826
 
3818
.done:
3827
.done:
3819
        mov     ebx, [ebp+NTFS.frs_buffer]
3828
        mov     ebx, [ebp+NTFS.frs_buffer]
3820
        mov     edx, [ebp+NTFS.rootLastRead]
3829
        mov     edx, [ebp+NTFS.rootLastRead]
3821
        call    writeRecord
3830
        call    writeRecord
3822
        mov     ebx, [ebp+NTFS.cur_index_buf]
3831
        mov     ebx, [ebp+NTFS.cur_index_buf]
3823
        cmp     dword [ebx], 'INDX'
3832
        cmp     dword [ebx], 'INDX'
3824
        jnz     @f
3833
        jnz     @f
3825
        mov     edx, [ebp+NTFS.nodeLastRead]
3834
        mov     edx, [ebp+NTFS.nodeLastRead]
3826
        call    writeRecord
3835
        call    writeRecord
3827
@@:
3836
@@:
3828
        mov     ebx, [ebp+NTFS.secondIndexBuffer]
3837
        mov     ebx, [ebp+NTFS.secondIndexBuffer]
3829
        cmp     byte [ebx], 0
3838
        cmp     byte [ebx], 0
3830
        jz      ntfsDone
3839
        jz      ntfsDone
3831
        mov     edx, [ebp+NTFS.LastRead]
3840
        mov     edx, [ebp+NTFS.LastRead]
3832
        call    writeRecord
3841
        call    writeRecord
3833
        jmp     ntfsDone
3842
        jmp     ntfsDone
3834
 
3843
 
3835
.findSubindex:
3844
.findSubindex:
3836
; in: eax -> index
3845
; in: eax -> index
3837
;   out:
3846
;   out:
3838
; CF=1 -> error
3847
; CF=1 -> error
3839
; esi=0 -> subnode deleted
3848
; esi=0 -> subnode deleted
3840
; esi -> replacement index
3849
; esi -> replacement index
3841
; eax = index effective size
3850
; eax = index effective size
3842
        movzx   edx, word [eax+indexAllocatedSize]
3851
        movzx   edx, word [eax+indexAllocatedSize]
3843
        mov     eax, [eax+edx-8]
3852
        mov     eax, [eax+edx-8]
3844
        mov     edx, [ebp+NTFS.cur_size]
3853
        mov     edx, [ebp+NTFS.cur_size]
3845
        push    edx
3854
        push    edx
3846
        cmp     edx, [ebp+NTFS.cur_subnode_size]
3855
        cmp     edx, [ebp+NTFS.cur_subnode_size]
3847
        jz      @f
3856
        jz      @f
3848
        mul     [ebp+NTFS.sectors_per_cluster]
3857
        mul     [ebp+NTFS.sectors_per_cluster]
3849
@@:
3858
@@:
3850
        mov     [ebp+NTFS.cur_attr], 0xA0
3859
        mov     [ebp+NTFS.cur_attr], 0xA0
3851
        mov     [ebp+NTFS.cur_offs], eax
3860
        mov     [ebp+NTFS.cur_offs], eax
3852
        push    eax
3861
        push    eax
3853
        mov     ebx, [ebp+NTFS.secondIndexBuffer]
3862
        mov     ebx, [ebp+NTFS.secondIndexBuffer]
3854
        mov     esi, ebx
3863
        mov     esi, ebx
3855
        mov     [ebp+NTFS.cur_buf], ebx
3864
        mov     [ebp+NTFS.cur_buf], ebx
3856
        call    ntfs_read_attr.newAttribute
3865
        call    ntfs_read_attr.newAttribute
3857
        pop     [ebp+NTFS.cur_offs]
3866
        pop     [ebp+NTFS.cur_offs]
3858
        pop     eax
3867
        pop     eax
3859
        jc      .ret
3868
        jc      .ret
3860
        cmp     dword [esi], 'INDX'
3869
        cmp     dword [esi], 'INDX'
3861
        stc
3870
        stc
3862
        jnz     .ret
3871
        jnz     .ret
3863
        mov     [ebp+NTFS.cur_size], eax
3872
        mov     [ebp+NTFS.cur_size], eax
3864
        shl     eax, 9
3873
        shl     eax, 9
3865
        call    ntfs_restore_usa
3874
        call    ntfs_restore_usa
3866
        jc      .ret
3875
        jc      .ret
3867
        add     esi, recordNode
3876
        add     esi, recordNode
3868
        add     esi, [esi+indexOffset]
3877
        add     esi, [esi+indexOffset]
3869
        test    byte [esi+indexFlags], 2
3878
        test    byte [esi+indexFlags], 2
3870
        jnz     .emptyNode
3879
        jnz     .emptyNode
3871
        cmp     [ebp+NTFS.fragmentCount], 1
3880
        cmp     [ebp+NTFS.fragmentCount], 1
3872
        stc
3881
        stc
3873
        jnz     .ret    ; record fragmented
3882
        jnz     .ret    ; record fragmented
3874
        xor     eax, eax
3883
        xor     eax, eax
3875
@@:
3884
@@:
3876
        add     esi, eax
3885
        add     esi, eax
3877
        mov     ax, [esi+indexAllocatedSize]
3886
        mov     ax, [esi+indexAllocatedSize]
3878
        test    byte [esi+eax+indexFlags], 2
3887
        test    byte [esi+eax+indexFlags], 2
3879
        jz      @b
3888
        jz      @b
3880
        test    byte [esi+indexFlags], 1
3889
        test    byte [esi+indexFlags], 1
3881
        jz      .ret
3890
        jz      .ret
3882
        add     eax, esi
3891
        add     eax, esi
3883
        push    esi
3892
        push    esi
3884
        push    [ebp+NTFS.cur_offs]
3893
        push    [ebp+NTFS.cur_offs]
3885
        call    .findSubindex
3894
        call    .findSubindex
3886
        pop     [ebp+NTFS.cur_offs]
3895
        pop     [ebp+NTFS.cur_offs]
3887
        pop     edx
3896
        pop     edx
3888
        jc      .ret
3897
        jc      .ret
3889
        test    esi, esi
3898
        test    esi, esi
3890
        jnz     .ret
3899
        jnz     .ret
3891
        mov     esi, edx
3900
        mov     esi, edx
3892
        mov     ebx, [ebp+NTFS.secondIndexBuffer]
3901
        mov     ebx, [ebp+NTFS.secondIndexBuffer]
3893
        mov     [ebp+NTFS.cur_buf], ebx
3902
        mov     [ebp+NTFS.cur_buf], ebx
3894
        push    [ebp+NTFS.cur_size]
3903
        push    [ebp+NTFS.cur_size]
3895
        call    ntfs_read_attr.continue
3904
        call    ntfs_read_attr.continue
3896
        pop     eax
3905
        pop     eax
3897
        jc      .ret
3906
        jc      .ret
3898
        shl     eax, 9
3907
        shl     eax, 9
3899
        call    ntfs_restore_usa
3908
        call    ntfs_restore_usa
3900
        jc      .ret
3909
        jc      .ret
3901
        movzx   eax, word [esi+indexAllocatedSize]
3910
        movzx   eax, word [esi+indexAllocatedSize]
3902
        sub     eax, 8
3911
        sub     eax, 8
3903
.ret:
3912
.ret:
3904
        ret
3913
        ret
3905
 
3914
 
3906
.emptyNode:
3915
.emptyNode:
3907
        test    byte [esi+indexFlags], 1
3916
        test    byte [esi+indexFlags], 1
3908
        jz      @f
3917
        jz      @f
3909
        mov     eax, esi
3918
        mov     eax, esi
3910
        push    [ebp+NTFS.cur_offs]
3919
        push    [ebp+NTFS.cur_offs]
3911
        call    .findSubindex
3920
        call    .findSubindex
3912
        pop     [ebp+NTFS.cur_offs]
3921
        pop     [ebp+NTFS.cur_offs]
3913
        jc      .ret
3922
        jc      .ret
3914
        test    esi, esi
3923
        test    esi, esi
3915
        jnz     .ret
3924
        jnz     .ret
3916
@@:         ; delete node
3925
@@:         ; delete node
3917
        mov     esi, [ebp+NTFS.attr_offs]
3926
        mov     esi, [ebp+NTFS.attr_offs]
3918
        add     esi, [esi+sizeWithHeader]
3927
        add     esi, [esi+sizeWithHeader]
3919
        cmp     byte [esi], 0xB0
3928
        cmp     byte [esi], 0xB0
3920
        stc
3929
        stc
3921
        jnz     .ret
3930
        jnz     .ret
3922
        movzx   eax, byte [esi+attributeOffset]
3931
        movzx   eax, byte [esi+attributeOffset]
3923
        add     esi, eax
3932
        add     esi, eax
3924
        mov     eax, [ebp+NTFS.cur_offs]
3933
        mov     eax, [ebp+NTFS.cur_offs]
3925
        xor     edx, edx
3934
        xor     edx, edx
3926
        div     [ebp+NTFS.cur_size]
3935
        div     [ebp+NTFS.cur_size]
3927
        mov     edx, eax
3936
        mov     edx, eax
3928
        shr     eax, 3
3937
        shr     eax, 3
3929
        and     edx, 7
3938
        and     edx, 7
3930
        btr     [esi+eax], edx
3939
        btr     [esi+eax], edx
3931
        mov     esi, [ebp+NTFS.secondIndexBuffer]
3940
        mov     esi, [ebp+NTFS.secondIndexBuffer]
3932
        mov     byte [esi], 0
3941
        mov     byte [esi], 0
3933
        xor     esi, esi
3942
        xor     esi, esi
3934
        ret
3943
        ret
3935
 
3944
 
3936
;----------------------------------------------------------------
3945
;----------------------------------------------------------------
3937
ntfs_SetFileEnd:
3946
ntfs_SetFileEnd:
3938
        call    ntfs_lock
3947
        call    ntfs_lock
3939
        call    ntfs_find_lfn
3948
        call    ntfs_find_lfn
3940
        jc      ntfsNotFound
3949
        jc      ntfsNotFound
3941
        cmp     [ebp+NTFS.cur_iRecord], 16
3950
        cmp     [ebp+NTFS.cur_iRecord], 16
3942
        jc      ntfsDenied
3951
        jc      ntfsDenied
3943
        test    dword [eax+fileFlags], 10000001h
3952
        test    dword [eax+fileFlags], 10000001h
3944
        jnz     ntfsDenied
3953
        jnz     ntfsDenied
3945
        cmp     [ebp+NTFS.fragmentCount], 1
3954
        cmp     [ebp+NTFS.fragmentCount], 1
3946
        jnz     ntfsUnsupported     ; record fragmented
3955
        jnz     ntfsUnsupported     ; record fragmented
3947
; edit directory node
3956
; edit directory node
3948
        mov     edi, [ebp+NTFS.cur_index_buf]
3957
        mov     edi, [ebp+NTFS.cur_index_buf]
3949
        cmp     dword [edi], 'INDX'
3958
        cmp     dword [edi], 'INDX'
3950
        jz      @f
3959
        jz      @f
3951
        mov     esi, [ebp+NTFS.frs_buffer]
3960
        mov     esi, [ebp+NTFS.frs_buffer]
3952
        mov     ecx, [esi+recordRealSize]
3961
        mov     ecx, [esi+recordRealSize]
3953
        shr     ecx, 2
3962
        shr     ecx, 2
3954
        rep movsd
3963
        rep movsd
3955
        mov     esi, [ebp+NTFS.attr_offs]
3964
        mov     esi, [ebp+NTFS.attr_offs]
3956
        mov     cl, [esi+attributeOffset]
3965
        mov     cl, [esi+attributeOffset]
3957
        sub     esi, [ebp+NTFS.frs_buffer]
3966
        sub     esi, [ebp+NTFS.frs_buffer]
3958
        add     eax, ecx
3967
        add     eax, ecx
3959
        add     eax, esi
3968
        add     eax, esi
3960
@@:
3969
@@:
3961
        mov     edi, eax
3970
        mov     edi, eax
3962
        mov     eax, [ebx+4]
3971
        mov     eax, [ebx+4]
3963
        mov     edx, [ebx+8]
3972
        mov     edx, [ebx+8]
3964
        mov     [edi+fileRealSize], eax
3973
        mov     [edi+fileRealSize], eax
3965
        mov     [edi+fileRealSize+4], edx
3974
        mov     [edi+fileRealSize+4], edx
3966
        push    edx eax ebx
3975
        push    edx eax ebx
3967
        call    ntfsGetTime
3976
        call    ntfsGetTime
3968
        mov     [edi+fileModified], eax
3977
        mov     [edi+fileModified], eax
3969
        mov     [edi+fileModified+4], edx
3978
        mov     [edi+fileModified+4], edx
3970
        mov     [edi+recordModified], eax
3979
        mov     [edi+recordModified], eax
3971
        mov     [edi+recordModified+4], edx
3980
        mov     [edi+recordModified+4], edx
3972
        mov     [edi+fileAccessed], eax
3981
        mov     [edi+fileAccessed], eax
3973
        mov     [edi+fileAccessed+4], edx
3982
        mov     [edi+fileAccessed+4], edx
3974
        pop     ebx ecx edx
3983
        pop     ebx ecx edx
3975
        mov     eax, [ebp+NTFS.LastRead]
3984
        mov     eax, [ebp+NTFS.LastRead]
3976
        mov     [ebp+NTFS.nodeLastRead], eax
3985
        mov     [ebp+NTFS.nodeLastRead], eax
3977
        mov     [ebp+NTFS.cur_attr], 0x80
3986
        mov     [ebp+NTFS.cur_attr], 0x80
3978
        mov     [ebp+NTFS.cur_offs], 0
3987
        mov     [ebp+NTFS.cur_offs], 0
3979
        mov     [ebp+NTFS.cur_size], 0
3988
        mov     [ebp+NTFS.cur_size], 0
3980
        call    ntfs_read_attr
3989
        call    ntfs_read_attr
3981
        jc      ntfsFail
3990
        jc      ntfsFail
3982
        mov     esi, edi
3991
        mov     esi, edi
3983
        mov     edi, [ebp+NTFS.frs_buffer]
3992
        mov     edi, [ebp+NTFS.frs_buffer]
3984
        cmp     word [edi+baseRecordReuse], 0
3993
        cmp     word [edi+baseRecordReuse], 0
3985
        jnz     ntfsUnsupported     ; auxiliary record
3994
        jnz     ntfsUnsupported     ; auxiliary record
3986
        mov     al, [edi+attributeOffset]
3995
        mov     al, [edi+attributeOffset]
3987
        add     edi, eax
3996
        add     edi, eax
3988
        mov     al, [edi+attributeOffset]
3997
        mov     al, [edi+attributeOffset]
3989
        add     edi, eax
3998
        add     edi, eax
3990
        mov     eax, ecx
3999
        mov     eax, ecx
3991
        mov     ecx, 6
4000
        mov     ecx, 6
3992
        add     esi, fileModified
4001
        add     esi, fileModified
3993
        add     edi, 8
4002
        add     edi, 8
3994
        rep movsd
4003
        rep movsd
3995
        mov     ecx, [ebp+NTFS.attr_offs]
4004
        mov     ecx, [ebp+NTFS.attr_offs]
3996
        cmp     word [ecx+attributeFlags], 0
4005
        cmp     word [ecx+attributeFlags], 0
3997
        jnz     ntfsUnsupported
4006
        jnz     ntfsUnsupported
3998
        cmp     byte [ecx+nonResidentFlag], 0
4007
        cmp     byte [ecx+nonResidentFlag], 0
3999
        jz      .resizeAttribute
4008
        jz      .resizeAttribute
4000
        cmp     [ecx+attributeRealSize+4], edx
4009
        cmp     [ecx+attributeRealSize+4], edx
4001
        jnz     .resizeAttribute
4010
        jnz     .resizeAttribute
4002
        cmp     [ecx+attributeRealSize], eax
4011
        cmp     [ecx+attributeRealSize], eax
4003
        jnc     .resizeAttribute
4012
        jnc     .resizeAttribute
4004
        mov     eax, [ecx+attributeRealSize]
4013
        mov     eax, [ecx+attributeRealSize]
4005
        mov     ecx, [ebp+NTFS.sectors_per_cluster]
4014
        mov     ecx, [ebp+NTFS.sectors_per_cluster]
4006
        mov     [ebp+NTFS.cur_size], ecx
4015
        mov     [ebp+NTFS.cur_size], ecx
4007
        shl     ecx, 9
4016
        shl     ecx, 9
4008
        div     ecx
4017
        div     ecx
4009
        test    edx, edx
4018
        test    edx, edx
4010
        jz      .aligned
4019
        jz      .aligned
4011
        push    edx
4020
        push    edx
4012
        push    ecx
4021
        push    ecx
4013
        mul     [ebp+NTFS.sectors_per_cluster]
4022
        mul     [ebp+NTFS.sectors_per_cluster]
4014
        mov     [ebp+NTFS.cur_offs], eax
4023
        mov     [ebp+NTFS.cur_offs], eax
4015
        stdcall kernel_alloc, ecx
4024
        stdcall kernel_alloc, ecx
4016
        pop     ecx
4025
        pop     ecx
4017
        pop     edi
4026
        pop     edi
4018
        mov     esi, eax
4027
        mov     esi, eax
4019
        sub     ecx, edi
4028
        sub     ecx, edi
4020
        add     edi, eax
4029
        add     edi, eax
4021
        mov     [ebp+NTFS.cur_buf], eax
4030
        mov     [ebp+NTFS.cur_buf], eax
4022
        call    ntfs_read_attr.continue
4031
        call    ntfs_read_attr.continue
4023
        jc      @f
4032
        jc      @f
4024
        xor     eax, eax
4033
        xor     eax, eax
4025
        rep stosb
4034
        rep stosb
4026
        push    ebx
4035
        push    ebx
4027
        mov     eax, [ebp+NTFS.LastRead]
4036
        mov     eax, [ebp+NTFS.LastRead]
4028
        mov     ebx, esi
4037
        mov     ebx, esi
4029
        mov     ecx, [ebp+NTFS.sectors_per_cluster]
4038
        mov     ecx, [ebp+NTFS.sectors_per_cluster]
4030
        xor     edx, edx
4039
        xor     edx, edx
4031
        call    fs_write64_app
4040
        call    fs_write64_app
4032
        pop     ebx
4041
        pop     ebx
4033
@@:
4042
@@:
4034
        stdcall kernel_free, esi
4043
        stdcall kernel_free, esi
4035
.aligned:
4044
.aligned:
4036
        mov     eax, [ebx+4]
4045
        mov     eax, [ebx+4]
4037
        mov     edx, [ebx+8]
4046
        mov     edx, [ebx+8]
4038
.resizeAttribute:
4047
.resizeAttribute:
4039
        call    resizeAttribute
4048
        call    resizeAttribute
4040
        jc      ntfsError
4049
        jc      ntfsError
4041
        mov     ebx, [ebp+NTFS.frs_buffer]
4050
        mov     ebx, [ebp+NTFS.frs_buffer]
4042
        mov     edx, [ebp+NTFS.mftLastRead]
4051
        mov     edx, [ebp+NTFS.mftLastRead]
4043
        call    writeRecord     ; file
4052
        call    writeRecord     ; file
4044
        mov     ebx, [ebp+NTFS.cur_index_buf]
4053
        mov     ebx, [ebp+NTFS.cur_index_buf]
4045
        mov     edx, [ebp+NTFS.nodeLastRead]
4054
        mov     edx, [ebp+NTFS.nodeLastRead]
4046
        call    writeRecord     ; directory
4055
        call    writeRecord     ; directory
4047
        call    ntfsSpaceClean
4056
        call    ntfsSpaceClean
4048
        jmp     ntfsDone
4057
        jmp     ntfsDone
4049
 
4058
 
4050
ntfsGetTime:
4059
ntfsGetTime:
4051
        call    fsGetTime
4060
        call    fsGetTime
4052
        jmp     @f
4061
        jmp     @f
4053
 
4062
 
4054
ntfsCalculateTime:
4063
ntfsCalculateTime:
4055
; in: esi -> data block
4064
; in: esi -> data block
4056
; out: edx:eax = seconds since 01.01.1601 x10000000
4065
; out: edx:eax = seconds since 01.01.1601 x10000000
4057
        call    fsCalculateTime
4066
        call    fsCalculateTime
4058
@@:
4067
@@:
4059
        mov     edx, 10000000
4068
        mov     edx, 10000000
4060
        mul     edx
4069
        mul     edx
4061
        add     eax, 3365781504
4070
        add     eax, 3365781504
4062
        adc     edx, 29389701
4071
        adc     edx, 29389701
4063
        ret
4072
        ret
4064
 
4073
 
4065
;----------------------------------------------------------------
4074
;----------------------------------------------------------------
4066
ntfs_SetFileInfo:
4075
ntfs_SetFileInfo:
4067
        call    ntfs_lock
4076
        call    ntfs_lock
4068
        call    ntfs_find_lfn
4077
        call    ntfs_find_lfn
4069
        jnc     @f
4078
        jnc     @f
4070
        test    eax, eax
4079
        test    eax, eax
4071
        jz      ntfsFail
4080
        jz      ntfsFail
4072
        jmp     ntfsNotFound
4081
        jmp     ntfsNotFound
4073
 
4082
 
4074
@@:
4083
@@:
4075
        cmp     [ebp+NTFS.fragmentCount], 1
4084
        cmp     [ebp+NTFS.fragmentCount], 1
4076
        jnz     ntfsUnsupported     ; record fragmented
4085
        jnz     ntfsUnsupported     ; record fragmented
4077
        mov     esi, [ebp+NTFS.cur_index_buf]
4086
        mov     esi, [ebp+NTFS.cur_index_buf]
4078
        cmp     dword [esi], 'INDX'
4087
        cmp     dword [esi], 'INDX'
4079
        jz      @f
4088
        jz      @f
4080
        sub     eax, esi
4089
        sub     eax, esi
4081
        mov     esi, [ebp+NTFS.indexRoot]
4090
        mov     esi, [ebp+NTFS.indexRoot]
4082
        movzx   edx, byte [esi+attributeOffset]
4091
        movzx   edx, byte [esi+attributeOffset]
4083
        add     eax, esi
4092
        add     eax, esi
4084
        add     eax, edx
4093
        add     eax, edx
4085
@@:
4094
@@:
4086
        mov     esi, [ebx+16]
4095
        mov     esi, [ebx+16]
4087
        mov     edi, eax
4096
        mov     edi, eax
4088
        mov     eax, [esi]
4097
        mov     eax, [esi]
4089
        and     eax, 27h
4098
        and     eax, 27h
4090
        and     byte [edi+fileFlags], -28h
4099
        and     byte [edi+fileFlags], -28h
4091
        or      [edi+fileFlags], al
4100
        or      [edi+fileFlags], al
4092
        add     esi, 8
4101
        add     esi, 8
4093
        call    ntfsCalculateTime
4102
        call    ntfsCalculateTime
4094
        mov     [edi+fileCreated], eax
4103
        mov     [edi+fileCreated], eax
4095
        mov     [edi+fileCreated+4], edx
4104
        mov     [edi+fileCreated+4], edx
4096
        add     esi, 8
4105
        add     esi, 8
4097
        call    ntfsCalculateTime
4106
        call    ntfsCalculateTime
4098
        mov     [edi+fileAccessed], eax
4107
        mov     [edi+fileAccessed], eax
4099
        mov     [edi+fileAccessed+4], edx
4108
        mov     [edi+fileAccessed+4], edx
4100
        add     esi, 8
4109
        add     esi, 8
4101
        call    ntfsCalculateTime
4110
        call    ntfsCalculateTime
4102
        mov     [edi+fileModified], eax
4111
        mov     [edi+fileModified], eax
4103
        mov     [edi+fileModified+4], edx
4112
        mov     [edi+fileModified+4], edx
4104
        mov     ebx, [ebp+NTFS.cur_index_buf]
4113
        mov     ebx, [ebp+NTFS.cur_index_buf]
4105
        cmp     dword [ebx], 'INDX'
4114
        cmp     dword [ebx], 'INDX'
4106
        jz      @f
4115
        jz      @f
4107
        mov     ebx, [ebp+NTFS.frs_buffer]
4116
        mov     ebx, [ebp+NTFS.frs_buffer]
4108
@@:
4117
@@:
4109
        mov     edx, [ebp+NTFS.LastRead]
4118
        mov     edx, [ebp+NTFS.LastRead]
4110
        call    writeRecord
4119
        call    writeRecord
4111
        jmp     ntfsDone
4120
        jmp     ntfsDone
4112
 
4121
 
4113
ntfsUnsupported:
4122
ntfsUnsupported:
4114
        push    ERROR_UNSUPPORTED_FS
4123
        push    ERROR_UNSUPPORTED_FS
4115
        jmp     ntfsOut
4124
        jmp     ntfsOut
4116
ntfsDevice:
4125
ntfsDevice:
4117
        push    ERROR_DEVICE
4126
        push    ERROR_DEVICE
4118
        jmp     ntfsOut
4127
        jmp     ntfsOut
4119
ntfsNotFound:
4128
ntfsNotFound:
4120
        push    ERROR_FILE_NOT_FOUND
4129
        push    ERROR_FILE_NOT_FOUND
4121
        jmp     ntfsOut
4130
        jmp     ntfsOut
4122
ntfsDenied:
4131
ntfsDenied:
4123
        push    ERROR_ACCESS_DENIED
4132
        push    ERROR_ACCESS_DENIED
4124
        jmp     ntfsOut
4133
        jmp     ntfsOut
4125
ntfsFail:
4134
ntfsFail:
4126
        push    ERROR_FS_FAIL
4135
        push    ERROR_FS_FAIL
4127
        jmp     ntfsOut
4136
        jmp     ntfsOut
4128
ntfsDiskFull:
4137
ntfsDiskFull:
4129
        push    ERROR_DISK_FULL
4138
        push    ERROR_DISK_FULL
4130
        jmp     ntfsOut
4139
        jmp     ntfsOut
4131
ntfsErrorPop5:
4140
ntfsErrorPop5:
4132
        pop     ebx
4141
        pop     ebx
4133
        pop     ebx
4142
        pop     ebx
4134
ntfsErrorPop3:
4143
ntfsErrorPop3:
4135
        pop     ebx
4144
        pop     ebx
4136
ntfsErrorPop2:
4145
ntfsErrorPop2:
4137
        pop     ebx
4146
        pop     ebx
4138
ntfsErrorPop:
4147
ntfsErrorPop:
4139
        pop     ebx
4148
        pop     ebx
4140
ntfsError:
4149
ntfsError:
4141
        push    eax
4150
        push    eax
4142
ntfsOut:
4151
ntfsOut:
4143
        call    ntfs_unlock
4152
        call    ntfs_unlock
4144
        xor     ebx, ebx
4153
        xor     ebx, ebx
4145
        pop     eax
4154
        pop     eax
4146
        ret
4155
        ret