1 #exe=1
2 /******************************************************************************
3 *
4 * Copyright (C) 2009, The Gentee Group. All rights reserved.
5 * This file is part of the Gentee open source project - http://www.gentee.com.
6 *
7 * THIS FILE IS PROVIDED UNDER THE TERMS OF THE GENTEE LICENSE ("AGREEMENT").
8 * ANY USE, REPRODUCTION OR DISTRIBUTION OF THIS FILE CONSTITUTES RECIPIENTS
9 * ACCEPTANCE OF THE AGREEMENT.
10 *
11 * Author: Alexey Krivonogov ( gentee )
12 *
13 ******************************************************************************/
14
15 include : $"..\other\random.g"
16
17 import "msvcrt"
18 {
19 int _close( int )
20 uint _get_errno( uint )
21 int _lseek( int, int, int )
22 int _open( uint, int, int )
23 int _read( int, uint, uint )
24 int remove( uint )
25 int _write( int, uint, uint )
26 }
27
28 define
29 {
30 CB_MAX_FILENAME = 256
31 CB_MAX_CABINET_NAME = 256
32 CB_MAX_CAB_PATH = 256
33 CB_MAX_DISK_NAME = 256
34 FOLDER_THRESHOLD = 1000000 // 900000
35 statusFile = 0 // Add File to Folder callback
36 statusFolder = 1 // Add Folder to Cabinet callback
37 statusCabinet = 2 // Write out a completed cabinet callback
38
39 FCIERR_NONE = 0
40 FCIERR_OPEN_SRC
41 FCIERR_READ_SRC
42 FCIERR_ALLOC_FAIL
43 FCIERR_TEMP_FILE
44 FCIERR_BAD_COMPR_TYPE
45 FCIERR_CAB_FILE
46 FCIERR_USER_ABORT
47 FCIERR_MCI_FAIL
48
49 }
50
51 type CCAB {
52 // LONG
53 uint cb // size available for cabinet on this media
54 uint cbFolderThresh // Thresshold for forcing a new Folder
55 // UINT
56 uint cbReserveCFHeader // Space to reserve in CFHEADER
57 uint cbReserveCFFolder // Space to reserve in CFFOLDER
58 uint cbReserveCFData // Space to reserve in CFDATA
59 int iCab // sequential numbers for cabinets
60 int iDisk // Disk number
61 //ifndef REMOVE_CHICAGO_M6_HACK
62 int fFailOnIncompressible // TRUE => Fail if a block is incompressible
63 //endif
64 ushort setID // Cabinet set ID
65
66 reserved szDisk[ $CB_MAX_DISK_NAME ] // current disk name
67 reserved szCab[ $CB_MAX_CABINET_NAME ] // current cabinet name
68 reserved szCabPath[ $CB_MAX_CAB_PATH ] // path for creating cabinet
69 }
70
71 type ERF
72 {
73 int erfOper
74 int erfType
75 uint fError
76 }
77
78 type cabinit
79 {
80 uint volumesize
81 str disk
82
83 uint fncerror
84 uint fncprogress
85
86 uint finish // 1 if finish for progress
87 uint cabsize
88 uint filesize
89 }
90
91 import "cabinet"
92 {
93 uint FCICreate( uint, uint, uint, uint, uint, uint, uint, uint, uint, uint,
94 uint, uint, uint )
95 uint FCIDestroy( uint )
96 uint FCIFlushCabinet( uint, uint, uint, uint )
97 }
98
99 import "cab2g.dll"<link>
100 {
101 uint gcabe_addfile( uint, uint, uint, uint )
102 uint gcabe_close( uint )
103 uint gcabe_create( CCAB )
104 }
105
106 method str str.gettempfile( str dir prefix )
107 {
108 random rnd
109
110 rnd.init()
111 rnd.randseed( 'A', 'Z' )
112 do
113 {
114 str name
115 uint i
116 fornum i, 6 : name.appendch( rnd.randseed() )
117 ( this = dir ).faddname( "\( prefix )\( name ).tmp" )
118 } while fileexist( this )
119
120 return this
121 }
122
123 func uint cab_alloc( uint size )
124 {
125 print("a=\( size )\n")
126 return malloc( size )
127 }
128
129 // -----------------------------------------------------------------
130
131 func cab_free( uint ptr )
132 {
133 print("0\n")
134 if ( ptr ) : mfree( ptr )
135 }
136
137 // -----------------------------------------------------------------
138
139 func int cab_open( uint name, int oflag pmode, uint err pv )
140 {
141 int result
142
143 print("1 \n")
144 // print("1 \("".copy( name ))\n")
145 // file ff
146 // ff.open( "".copy( name ), $OP_ALWAYS )
147 // result = ff.handle
148 result = _open( name, oflag, pmode)
149
150 if result == -1 : _get_errno( err )
151 print("1 \(result) \(err)\n")
152
153 return result
154 }
155
156 // -----------------------------------------------------------------
157
158 func uint cab_read( int hf, uint memory cb err userpar )
159 {
160 uint result
161
162 print("2\n")
163 result = _read( hf, memory, cb )
164
165 if result != cb : _get_errno( err )
166
167 return result
168 }
169
170 // -----------------------------------------------------------------
171
172 func uint cab_write( int hf, uint memory cb err userpar )
173 {
174 uint result
175
176 print("3\n")
177 result = _write( hf, memory, cb )
178
179 if result != cb : _get_errno( err )
180
181 return result
182 }
183
184 // -----------------------------------------------------------------
185
186 func int cab_close( int hf, uint err userpar )
187 {
188 int result
189
190 print("4\n")
191 result = _close( hf )
192 if result != 0 : _get_errno( err )
193
194 return result
195 }
196
197 // -----------------------------------------------------------------
198
199 func int cab_seek( int hf, int dist seektype, uint err userpar )
200 {
201 int result;
202
203 print("5\n")
204 result = _lseek( hf, dist, seektype );
205
206 if result == -1 : _get_errno( err )
207
208 return result
209 }
210
211 // -----------------------------------------------------------------
212
213 func int cab_delete( uint name, uint err pv )
214 {
215 int result
216
217 print("6\n")
218 result = remove( name )
219
220 if result != 0 : _get_errno( err )
221
222 return result
223 }
224
225 //--------------------------------------------------------------------------
226
227 func int cab_placed( CCAB pccab, uint filename, uint size continuation pv )
228 {
229 print("7 cab=\(&pccab ) \("".copy( filename )) \( size ) \(continuation) cabi=\(pv) \( pv->uint )\n")
230 /* printf("Placed file '%s' (size %d) on cabinet '%s'\n",
231 filename, size, pccab->szCab );
232
233 if (fContinuation)
234 printf(" (Above file is a later segment of a continued file)\n");
235 */
236 return 0
237 }
238
239 func uint cab_gettempfile( uint ret, int length, uint pv )
240 {
241 str dir filename
242
243 print("8\n")
244 gettempdir( dir )
245 // filename.gettempfile( dir, "cab_" )
246 uint i
247 do
248 {
249 ( filename = dir ).faddname( "cab_\(i++).tmp" )
250 } while fileexist( filename )
251 if ( *filename + 1 ) < length
252 {
253 mcopy( ret, filename.ptr(), *filename + 1 )
254 print("81 \( filename )\n")
255 return 1
256 }
257 return 0
258 }
259
260 // -----------------------------------------------------------------
261
262 func cab_error( cabinit cabi, uint code, str prefix )
263 {
264 str strerr
265
266 print("9\n")
267 if !cabi.fncerror : return
268
269 switch code
270 {
271 case $FCIERR_NONE : strerr = "No error"
272 case $FCIERR_OPEN_SRC: strerr = "Failure opening file to be stored in cabinet"
273 case $FCIERR_READ_SRC: strerr = "Failure reading file to be stored in cabinet"
274 case $FCIERR_ALLOC_FAIL: strerr = "Insufficient memory in FCI"
275 case $FCIERR_TEMP_FILE: strerr = "Could not create a temporary file"
276 case $FCIERR_BAD_COMPR_TYPE: strerr = "Unknown compression type"
277 case $FCIERR_CAB_FILE: strerr = "Could not create cabinet file"
278 case $FCIERR_USER_ABORT: strerr = "Client requested abort"
279 case $FCIERR_MCI_FAIL: strerr = "Failure compressing data"
280 default : strerr = "Unknown error"
281 }
282 cabi.fncerror->func( "\(prefix) failed: \(code) [\(strerr)]")
283 }
284
285 // -----------------------------------------------------------------
286
287 func uint cab_progress( uint status cb1 cb2 pv )
288 {
289 uint percent cabi
290
291 cabi = pv
292 cabi as cabinit
293
294 if status == $statusFile && !cabi.finish
295 {
296 cabi.cabsize += cb2;
297 if cabi.filesize : percent = 100 * cabi.cabsize / cabi.filesize
298 if cabi.fncprogress : cabi.fncprogress->func( cabi, percent )
299 }
300 /* else if (typeStatus == statusFolder)
301 {
302 int percentage;
303
304 percentage = get_percentage(cb1, cb2);
305
306 printf("\nCopying folder to cabinet: %d%% \r", percentage);
307 }*/
308 return 0;
309 }
310
311
312 func uint cab_netxcabinet( CCAB pccab, uint cbPrevCab pv )
313 {
314 uint cabi = pv
315 str name
316
317 cabi as cabinit
318
319 name.printf( cabi.disk, %{ pccab.iCab } )
320 mcopy( &pccab.szCab, name.ptr(), *name + 1 )
321 return 1
322 }
323
324
325 func uint mycallback( uint idfunc, uint parsize )
326 {
327 buf bc = '\h
328 50
329 55
330 53
331 8B DC
332 83 C3 \(byte( parsize * 4 + 0x0C ))
333 8B EB
334 83 ED \(byte( parsize * 4 ))
335 3B EB
336 74 08
337 8B 03
338 50
339 83 EB 04
340 EB F4
341 83 ED 04
342 55
343 68 \( idfunc )
344 b8 \( calladdr() )
345 ff d0
346 83 C4 \(byte( ( parsize +2 )* 4 ))
347 5B
348 5D
349 58
350 C2 \( parsize * 4 )
351 00
352 '
353 uint pmem
354 pmem = VirtualAlloc( 0, *bc + 100, 0x3000, 0x40 )
355 //print( "mem = \(hex2strl(pmem))\n" )
356 mcopy( pmem, bc.ptr(), *bc )
357 return pmem
358
359 }
360
361 // -----------------------------------------------------------------
362
363 func uint cab_create( str path cabfile, arrstr files, cabinit cabi )
364 {
365 CCAB ccab
366 uint hfci ret
367 ERF erf
368 arr fncid of uint
369 arr fnc of uint
370 uint i
371
372 fncid = %{ &cab_placed, &cab_alloc, &cab_free,
373 &cab_open, &cab_read, &cab_write, &cab_close,
374 &cab_seek, &cab_delete, &cab_gettempfile, &cab_progress,
375 &cab_netxcabinet }
376 fnc = %{ 5, 1, 1, 5, 5, 5, 3, 5, 3, 3, 4, 3 }
377 fornum i, *fnc
378 {
379 // uint par = fnc[i]
380 fnc[i] = mycallback( fncid[i], fnc[i] )
381 print("\(i)=\(fncid[i]) \(fnc[i])\n")
382 }
383 cabi.finish = 0
384 cabi.cabsize = 0
385 cabi.filesize = 0
386
387 ccab.cb = cabi.volumesize
388 ccab.cbFolderThresh = $FOLDER_THRESHOLD
389 ccab.cbReserveCFHeader = 0
390 ccab.cbReserveCFFolder = 0
391 ccab.cbReserveCFData = 0
392 ccab.iCab = 1
393 ccab.iDisk = 0
394 ccab.setID = 777
395 print("0 cab = \( &ccab ) cabi = \(&cabi )\n")
396 mcopy( &ccab.szDisk, cabi.disk.ptr(), *cabi.disk + 1 )
397 mcopy( &ccab.szCabPath, path.ptr(), *path + 1 )
398 mcopy( &ccab.szCab, cabfile.ptr(), *cabfile + 1 )
399 // store_cab_name(cab_parms->szCab, cab_parms->iCab);
400
401 hfci = gcabe_create( ccab )
402 // hfci = FCICreate( &erf, fnc[0], fnc[1], fnc[2], fnc[3], fnc[4], fnc[5],
403 // fnc[6], fnc[7], fnc[8], fnc[9], &ccab, &cabi )
404 print("ОК 2\n")
405 if !hfci
406 {
407 cab_error( cabi, erf.erfOper, "FCICreate" )
408 goto end
409 }
410 cabi.finish = 1
411 print("ОК 3\n")
412 /* if !FCIFlushCabinet( hfci, 0, fnc[11], fnc[10] )
413 {
414 print("ОК 4\n")
415
416 cab_error( cabi, erf.erfOper, "FCIFlushCabinet" )
417 goto end
418 }
419 print("ОК 5\n")
420
421 FCIDestroy( hfci )*/
422 fornum i = 0, *files
423 {
424 ffind fd
425
426 fd.init( files[i], $FIND_FILE | $FIND_RECURSE )
427 foreach cur, fd
428 {
429 gcabe_addfile( hfci, cur.fullname.ptr(), cur.name.ptr(), 0 )
430 }
431 }
432 gcabe_close( hfci )
433 ret = 1
434 label end:
435 fornum i = 0, *fnc : freecallback( fnc[i] )
436 return ret
437 }
438
439 func main<main>
440 {
441 cabinit cabi
442 arrstr files = %{"c:\\temp\\*.*"}
443
444 cabi.volumesize = 300000
445 cabi.disk = "mydisk"
446 cab_create( $"c:\\temp\\", "test.cab", files, cabi )
447 congetch("Press any key...")
448 }