usp10: Update tests in test_ScriptItemIzeShapePlace to match Windows results.
[wine/multimedia.git] / dlls / ntdll / tape.c
blob2767d1ddd85ef919e7a6a877a8fb9ff1f8fb67bc
1 /*
2 * TAPE support
4 * Copyright 2006 Hans Leidekker
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #include "config.h"
22 #include "wine/port.h"
24 #include <stdarg.h>
25 #include <stdio.h>
26 #ifdef HAVE_SYS_IOCTL_H
27 #include <sys/ioctl.h>
28 #endif
29 #ifdef HAVE_SYS_MTIO_H
30 #include <sys/mtio.h>
31 #endif
33 #if !defined(MTCOMPRESSION) && defined(MTCOMP)
34 #define MTCOMPRESSION MTCOMP
35 #endif
36 #if !defined(MTSETBLK) && defined(MTSETBSIZ)
37 #define MTSETBLK MTSETBSIZ
38 #endif
40 #define NONAMELESSUNION
41 #define NONAMELESSSTRUCT
42 #include "ntstatus.h"
43 #define WIN32_NO_STATUS
44 #include "windef.h"
45 #include "winternl.h"
46 #include "winioctl.h"
47 #include "ddk/ntddtape.h"
48 #include "ntdll_misc.h"
49 #include "wine/server.h"
50 #include "wine/debug.h"
52 WINE_DEFAULT_DEBUG_CHANNEL(tape);
54 static const char *io2str( DWORD io )
56 switch (io)
58 #define X(x) case (x): return #x;
59 X(IOCTL_TAPE_CHECK_VERIFY);
60 X(IOCTL_TAPE_CREATE_PARTITION);
61 X(IOCTL_TAPE_ERASE);
62 X(IOCTL_TAPE_FIND_NEW_DEVICES);
63 X(IOCTL_TAPE_GET_DRIVE_PARAMS);
64 X(IOCTL_TAPE_GET_MEDIA_PARAMS);
65 X(IOCTL_TAPE_GET_POSITION);
66 X(IOCTL_TAPE_GET_STATUS);
67 X(IOCTL_TAPE_PREPARE);
68 X(IOCTL_TAPE_SET_DRIVE_PARAMS);
69 X(IOCTL_TAPE_SET_MEDIA_PARAMS);
70 X(IOCTL_TAPE_SET_POSITION);
71 X(IOCTL_TAPE_WRITE_MARKS);
72 #undef X
73 default: { static char tmp[32]; sprintf(tmp, "IOCTL_TAPE_%ld\n", io); return tmp; }
77 /******************************************************************
78 * TAPE_GetStatus
80 static NTSTATUS TAPE_GetStatus( int error )
82 if (!error) return STATUS_SUCCESS;
83 return FILE_GetNtStatus();
86 /******************************************************************
87 * TAPE_CreatePartition
89 static NTSTATUS TAPE_CreatePartition( int fd, TAPE_CREATE_PARTITION *data )
91 #ifdef HAVE_SYS_MTIO_H
92 struct mtop cmd;
94 TRACE( "fd: %d method: 0x%08lx count: 0x%08lx size: 0x%08lx\n",
95 fd, data->Method, data->Count, data->Size );
97 if (data->Count > 1)
99 WARN( "Creating more than 1 partition is not supported\n" );
100 return STATUS_INVALID_PARAMETER;
103 switch (data->Method)
105 #ifdef MTMKPART
106 case TAPE_FIXED_PARTITIONS:
107 case TAPE_SELECT_PARTITIONS:
108 cmd.mt_op = MTMKPART;
109 cmd.mt_count = 0;
110 break;
111 case TAPE_INITIATOR_PARTITIONS:
112 cmd.mt_op = MTMKPART;
113 cmd.mt_count = data->Size;
114 break;
115 #endif
116 default:
117 ERR( "Unhandled method: 0x%08lx\n", data->Method );
118 return STATUS_INVALID_PARAMETER;
121 return TAPE_GetStatus( ioctl( fd, MTIOCTOP, &cmd ) );
122 #else
123 FIXME( "Not implemented.\n" );
124 return STATUS_NOT_SUPPORTED;
125 #endif
128 /******************************************************************
129 * TAPE_Erase
131 static NTSTATUS TAPE_Erase( int fd, TAPE_ERASE *data )
133 #ifdef HAVE_SYS_MTIO_H
134 struct mtop cmd;
136 TRACE( "fd: %d type: 0x%08lx immediate: 0x%02x\n",
137 fd, data->Type, data->Immediate );
139 switch (data->Type)
141 case TAPE_ERASE_LONG:
142 cmd.mt_op = MTERASE;
143 cmd.mt_count = 1;
144 break;
145 case TAPE_ERASE_SHORT:
146 cmd.mt_op = MTERASE;
147 cmd.mt_count = 0;
148 break;
149 default:
150 ERR( "Unhandled type: 0x%08lx\n", data->Type );
151 return STATUS_INVALID_PARAMETER;
154 return TAPE_GetStatus( ioctl( fd, MTIOCTOP, &cmd ) );
155 #else
156 FIXME( "Not implemented.\n" );
157 return STATUS_NOT_SUPPORTED;
158 #endif
161 /******************************************************************
162 * TAPE_GetDriveParams
164 static NTSTATUS TAPE_GetDriveParams( int fd, TAPE_GET_DRIVE_PARAMETERS *data )
166 #ifdef HAVE_SYS_MTIO_H
167 struct mtget get;
168 NTSTATUS status;
170 TRACE( "fd: %d\n", fd );
172 memset( data, 0, sizeof(TAPE_GET_DRIVE_PARAMETERS) );
174 status = TAPE_GetStatus( ioctl( fd, MTIOCGET, &get ) );
175 if (status != STATUS_SUCCESS)
176 return status;
178 data->ECC = FALSE;
179 data->Compression = FALSE;
180 data->DataPadding = FALSE;
181 data->ReportSetmarks = FALSE;
182 #ifdef HAVE_STRUCT_MTGET_MT_BLKSIZ
183 data->DefaultBlockSize = get.mt_blksiz;
184 #else
185 data->DefaultBlockSize = get.mt_dsreg & MT_ST_BLKSIZE_MASK;
186 #endif
187 data->MaximumBlockSize = data->DefaultBlockSize;
188 data->MinimumBlockSize = data->DefaultBlockSize;
189 data->MaximumPartitionCount = 1;
191 return status;
192 #else
193 FIXME( "Not implemented.\n" );
194 return STATUS_NOT_SUPPORTED;
195 #endif
198 /******************************************************************
199 * TAPE_GetMediaParams
201 static NTSTATUS TAPE_GetMediaParams( int fd, TAPE_GET_MEDIA_PARAMETERS *data )
203 #ifdef HAVE_SYS_MTIO_H
204 struct mtget get;
205 NTSTATUS status;
207 TRACE( "fd: %d\n", fd );
209 memset( data, 0, sizeof(TAPE_GET_MEDIA_PARAMETERS) );
211 status = TAPE_GetStatus( ioctl( fd, MTIOCGET, &get ) );
212 if (status != STATUS_SUCCESS)
213 return status;
215 data->Capacity.u.LowPart = 1024 * 1024 * 1024;
216 data->Remaining.u.LowPart = 1024 * 1024 * 1024;
217 #ifdef HAVE_STRUCT_MTGET_MT_BLKSIZ
218 data->BlockSize = get.mt_blksiz;
219 #else
220 data->BlockSize = get.mt_dsreg & MT_ST_BLKSIZE_MASK;
221 #endif
222 data->PartitionCount = 1;
223 #ifdef HAVE_STRUCT_MTGET_MT_GSTAT
224 data->WriteProtected = GMT_WR_PROT(get.mt_gstat);
225 #else
226 data->WriteProtected = 0;
227 #endif
229 return status;
230 #else
231 FIXME( "Not implemented.\n" );
232 return STATUS_NOT_SUPPORTED;
233 #endif
236 /******************************************************************
237 * TAPE_GetPosition
239 static NTSTATUS TAPE_GetPosition( int fd, ULONG type, TAPE_GET_POSITION *data )
241 #ifdef HAVE_SYS_MTIO_H
242 struct mtget get;
243 #ifndef HAVE_STRUCT_MTGET_MT_BLKNO
244 struct mtpos pos;
245 #endif
246 NTSTATUS status;
248 TRACE( "fd: %d type: 0x%08lx\n", fd, type );
250 memset( data, 0, sizeof(TAPE_GET_POSITION) );
252 status = TAPE_GetStatus( ioctl( fd, MTIOCGET, &get ) );
253 if (status != STATUS_SUCCESS)
254 return status;
256 #ifndef HAVE_STRUCT_MTGET_MT_BLKNO
257 status = TAPE_GetStatus( ioctl( fd, MTIOCPOS, &pos ) );
258 if (status != STATUS_SUCCESS)
259 return status;
260 #endif
262 switch (type)
264 case TAPE_ABSOLUTE_BLOCK:
265 data->Type = type;
266 data->Partition = get.mt_resid;
267 #ifdef HAVE_STRUCT_MTGET_MT_BLKNO
268 data->OffsetLow = get.mt_blkno;
269 #else
270 data->OffsetLow = pos.mt_blkno;
271 #endif
272 break;
273 case TAPE_LOGICAL_BLOCK:
274 case TAPE_PSEUDO_LOGICAL_BLOCK:
275 WARN( "Positioning type not supported\n" );
276 break;
277 default:
278 ERR( "Unhandled type: 0x%08lx\n", type );
279 return STATUS_INVALID_PARAMETER;
282 return status;
283 #else
284 FIXME( "Not implemented.\n" );
285 return STATUS_NOT_SUPPORTED;
286 #endif
289 /******************************************************************
290 * TAPE_Prepare
292 static NTSTATUS TAPE_Prepare( int fd, TAPE_PREPARE *data )
294 #ifdef HAVE_SYS_MTIO_H
295 struct mtop cmd;
297 TRACE( "fd: %d type: 0x%08lx immediate: 0x%02x\n",
298 fd, data->Operation, data->Immediate );
300 switch (data->Operation)
302 #ifdef MTLOAD
303 case TAPE_LOAD:
304 cmd.mt_op = MTLOAD;
305 break;
306 #endif
307 #ifdef MTUNLOAD
308 case TAPE_UNLOAD:
309 cmd.mt_op = MTUNLOAD;
310 break;
311 #endif
312 #ifdef MTRETEN
313 case TAPE_TENSION:
314 cmd.mt_op = MTRETEN;
315 break;
316 #endif
317 #ifdef MTLOCK
318 case TAPE_LOCK:
319 cmd.mt_op = MTLOCK;
320 break;
321 #endif
322 #ifdef MTUNLOCK
323 case TAPE_UNLOCK:
324 cmd.mt_op = MTUNLOCK;
325 break;
326 #endif
327 case TAPE_FORMAT:
328 /* Native ignores this if the drive doesn't support it */
329 return STATUS_SUCCESS;
330 default:
331 ERR( "Unhandled operation: 0x%08lx\n", data->Operation );
332 return STATUS_INVALID_PARAMETER;
335 return TAPE_GetStatus( ioctl( fd, MTIOCTOP, &cmd ) );
336 #else
337 FIXME( "Not implemented.\n" );
338 return STATUS_NOT_SUPPORTED;
339 #endif
342 /******************************************************************
343 * TAPE_SetDriveParams
345 static NTSTATUS TAPE_SetDriveParams( int fd, TAPE_SET_DRIVE_PARAMETERS *data )
347 #if defined(HAVE_SYS_MTIO_H) && defined(MTCOMPRESSION)
348 struct mtop cmd;
350 TRACE( "fd: %d ECC: 0x%02x, compression: 0x%02x padding: 0x%02x\n",
351 fd, data->ECC, data->Compression, data->DataPadding );
352 TRACE( "setmarks: 0x%02x zonesize: 0x%08lx\n",
353 data->ReportSetmarks, data->EOTWarningZoneSize );
355 if (data->ECC || data->DataPadding || data->ReportSetmarks ||
356 data->EOTWarningZoneSize ) WARN( "Setting not supported\n" );
358 cmd.mt_op = MTCOMPRESSION;
359 cmd.mt_count = data->Compression;
361 return TAPE_GetStatus( ioctl( fd, MTIOCTOP, &cmd ) );
362 #else
363 FIXME( "Not implemented.\n" );
364 return STATUS_NOT_SUPPORTED;
365 #endif
368 /******************************************************************
369 * TAPE_SetMediaParams
371 static NTSTATUS TAPE_SetMediaParams( int fd, TAPE_SET_MEDIA_PARAMETERS *data )
373 #ifdef HAVE_SYS_MTIO_H
374 struct mtop cmd;
376 TRACE( "fd: %d blocksize: 0x%08lx\n", fd, data->BlockSize );
378 cmd.mt_op = MTSETBLK;
379 cmd.mt_count = data->BlockSize;
381 return TAPE_GetStatus( ioctl( fd, MTIOCTOP, &cmd ) );
382 #else
383 FIXME( "Not implemented.\n" );
384 return STATUS_NOT_SUPPORTED;
385 #endif
388 /******************************************************************
389 * TAPE_SetPosition
391 static NTSTATUS TAPE_SetPosition( int fd, TAPE_SET_POSITION *data )
393 #ifdef HAVE_SYS_MTIO_H
394 struct mtop cmd;
396 TRACE( "fd: %d method: 0x%08lx partition: 0x%08lx offset: 0x%08lx immediate: 0x%02x\n",
397 fd, data->Method, data->Partition, data->Offset.u.LowPart, data->Immediate );
399 if (data->Offset.u.HighPart > 0)
400 return STATUS_INVALID_PARAMETER;
402 switch (data->Method)
404 case TAPE_REWIND:
405 cmd.mt_op = MTREW;
406 break;
407 #ifdef MTSEEK
408 case TAPE_ABSOLUTE_BLOCK:
409 cmd.mt_op = MTSEEK;
410 cmd.mt_count = data->Offset.u.LowPart;
411 break;
412 #endif
413 #ifdef MTEOM
414 case TAPE_SPACE_END_OF_DATA:
415 cmd.mt_op = MTEOM;
416 break;
417 #endif
418 case TAPE_SPACE_FILEMARKS:
419 if (data->Offset.u.LowPart >= 0) {
420 cmd.mt_op = MTFSF;
421 cmd.mt_count = data->Offset.u.LowPart;
423 else {
424 cmd.mt_op = MTBSF;
425 cmd.mt_count = -data->Offset.u.LowPart;
427 break;
428 #if defined(MTFSS) && defined(MTBSS)
429 case TAPE_SPACE_SETMARKS:
430 if (data->Offset.u.LowPart >= 0) {
431 cmd.mt_op = MTFSS;
432 cmd.mt_count = data->Offset.u.LowPart;
434 else {
435 cmd.mt_op = MTBSS;
436 cmd.mt_count = -data->Offset.u.LowPart;
438 break;
439 #endif
440 case TAPE_LOGICAL_BLOCK:
441 case TAPE_PSEUDO_LOGICAL_BLOCK:
442 case TAPE_SPACE_RELATIVE_BLOCKS:
443 case TAPE_SPACE_SEQUENTIAL_FMKS:
444 case TAPE_SPACE_SEQUENTIAL_SMKS:
445 WARN( "Positioning method not supported\n" );
446 return STATUS_INVALID_PARAMETER;
447 default:
448 ERR( "Unhandled method: 0x%08lx\n", data->Method );
449 return STATUS_INVALID_PARAMETER;
452 return TAPE_GetStatus( ioctl( fd, MTIOCTOP, &cmd ) );
453 #else
454 FIXME( "Not implemented.\n" );
455 return STATUS_NOT_SUPPORTED;
456 #endif
459 /******************************************************************
460 * TAPE_WriteMarks
462 static NTSTATUS TAPE_WriteMarks( int fd, TAPE_WRITE_MARKS *data )
464 #ifdef HAVE_SYS_MTIO_H
465 struct mtop cmd;
467 TRACE( "fd: %d type: 0x%08lx count: 0x%08lx immediate: 0x%02x\n",
468 fd, data->Type, data->Count, data->Immediate );
470 switch (data->Type)
472 #ifdef MTWSM
473 case TAPE_SETMARKS:
474 cmd.mt_op = MTWSM;
475 cmd.mt_count = data->Count;
476 break;
477 #endif
478 case TAPE_FILEMARKS:
479 case TAPE_SHORT_FILEMARKS:
480 case TAPE_LONG_FILEMARKS:
481 cmd.mt_op = MTWEOF;
482 cmd.mt_count = data->Count;
483 break;
484 default:
485 ERR( "Unhandled type: 0x%08lx\n", data->Type );
486 return STATUS_INVALID_PARAMETER;
489 return TAPE_GetStatus( ioctl( fd, MTIOCTOP, &cmd ) );
490 #else
491 FIXME( "Not implemented.\n" );
492 return STATUS_NOT_SUPPORTED;
493 #endif
496 /******************************************************************
497 * TAPE_DeviceIoControl
499 * SEE ALSO
500 * NtDeviceIoControl.
502 NTSTATUS TAPE_DeviceIoControl( HANDLE device, HANDLE event,
503 PIO_APC_ROUTINE apc, PVOID apc_user, PIO_STATUS_BLOCK io_status,
504 ULONG io_control, LPVOID in_buffer, DWORD in_size,
505 LPVOID out_buffer, DWORD out_size )
507 DWORD sz = 0;
508 NTSTATUS status = STATUS_INVALID_PARAMETER;
509 int fd;
511 TRACE( "%p %s %p %ld %p %ld %p\n", device, io2str(io_control),
512 in_buffer, in_size, out_buffer, out_size, io_status );
514 io_status->Information = 0;
516 if ((status = wine_server_handle_to_fd( device, 0, &fd, NULL )))
517 goto error;
519 switch (io_control)
521 case IOCTL_TAPE_CREATE_PARTITION:
522 status = TAPE_CreatePartition( fd, (TAPE_CREATE_PARTITION *)in_buffer );
523 break;
524 case IOCTL_TAPE_ERASE:
525 status = TAPE_Erase( fd, (TAPE_ERASE *)in_buffer );
526 break;
527 case IOCTL_TAPE_GET_DRIVE_PARAMS:
528 status = TAPE_GetDriveParams( fd, (TAPE_GET_DRIVE_PARAMETERS *)out_buffer );
529 break;
530 case IOCTL_TAPE_GET_MEDIA_PARAMS:
531 status = TAPE_GetMediaParams( fd, (TAPE_GET_MEDIA_PARAMETERS *)out_buffer );
532 break;
533 case IOCTL_TAPE_GET_POSITION:
534 status = TAPE_GetPosition( fd, ((TAPE_GET_POSITION *)in_buffer)->Type,
535 (TAPE_GET_POSITION *)out_buffer );
536 break;
537 case IOCTL_TAPE_GET_STATUS:
538 status = FILE_GetNtStatus();
539 break;
540 case IOCTL_TAPE_PREPARE:
541 status = TAPE_Prepare( fd, (TAPE_PREPARE *)in_buffer );
542 break;
543 case IOCTL_TAPE_SET_DRIVE_PARAMS:
544 status = TAPE_SetDriveParams( fd, (TAPE_SET_DRIVE_PARAMETERS *)in_buffer );
545 break;
546 case IOCTL_TAPE_SET_MEDIA_PARAMS:
547 status = TAPE_SetMediaParams( fd, (TAPE_SET_MEDIA_PARAMETERS *)in_buffer );
548 break;
549 case IOCTL_TAPE_SET_POSITION:
550 status = TAPE_SetPosition( fd, (TAPE_SET_POSITION *)in_buffer );
551 break;
552 case IOCTL_TAPE_WRITE_MARKS:
553 status = TAPE_WriteMarks( fd, (TAPE_WRITE_MARKS *)in_buffer );
554 break;
556 case IOCTL_TAPE_CHECK_VERIFY:
557 case IOCTL_TAPE_FIND_NEW_DEVICES:
558 break;
559 default:
560 FIXME( "Unsupported IOCTL %lx (type=%lx access=%lx func=%lx meth=%lx)\n",
561 io_control, io_control >> 16, (io_control >> 14) & 3,
562 (io_control >> 2) & 0xfff, io_control & 3 );
563 break;
566 wine_server_release_fd( device, fd );
568 error:
569 io_status->u.Status = status;
570 io_status->Information = sz;
571 if (event) NtSetEvent( event, NULL );
572 return status;