ntdll: Make sure we don't try to attach the main exe a second time.
[wine/zf.git] / dlls / ntdll / tape.c
blob90505847b1e53efa0e4cd79900595f6d8a01825a
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
39 #if !defined(MTSETBLK) && defined(MTSRSZ)
40 #define MTSETBLK MTSRSZ
41 #endif
42 #ifndef MT_ST_BLKSIZE_MASK
43 #define MT_ST_BLKSIZE_MASK 0xffffff
44 #endif
46 /* Darwin 7.9.0 has MTSETBSIZ instead of MTSETBLK */
47 #if !defined(MTSETBLK) && defined(MTSETBSIZ)
48 #define MTSETBLK MTSETBSIZ
49 #endif
51 #include "ntstatus.h"
52 #define WIN32_NO_STATUS
53 #define NONAMELESSUNION
54 #include "windef.h"
55 #include "winternl.h"
56 #include "winioctl.h"
57 #include "ddk/ntddtape.h"
58 #include "ntdll_misc.h"
59 #include "wine/server.h"
60 #include "wine/debug.h"
62 WINE_DEFAULT_DEBUG_CHANNEL(tape);
64 static const char *io2str( DWORD io )
66 switch (io)
68 #define X(x) case (x): return #x
69 X(IOCTL_TAPE_CHECK_VERIFY);
70 X(IOCTL_TAPE_CREATE_PARTITION);
71 X(IOCTL_TAPE_ERASE);
72 X(IOCTL_TAPE_FIND_NEW_DEVICES);
73 X(IOCTL_TAPE_GET_DRIVE_PARAMS);
74 X(IOCTL_TAPE_GET_MEDIA_PARAMS);
75 X(IOCTL_TAPE_GET_POSITION);
76 X(IOCTL_TAPE_GET_STATUS);
77 X(IOCTL_TAPE_PREPARE);
78 X(IOCTL_TAPE_SET_DRIVE_PARAMS);
79 X(IOCTL_TAPE_SET_MEDIA_PARAMS);
80 X(IOCTL_TAPE_SET_POSITION);
81 X(IOCTL_TAPE_WRITE_MARKS);
82 #undef X
83 default: { static char tmp[32]; sprintf(tmp, "IOCTL_TAPE_%d\n", io); return tmp; }
87 /******************************************************************
88 * TAPE_GetStatus
90 #ifdef HAVE_SYS_MTIO_H
91 static inline NTSTATUS TAPE_GetStatus( int error )
93 if (!error) return STATUS_SUCCESS;
94 return FILE_GetNtStatus();
96 #endif
98 /******************************************************************
99 * TAPE_CreatePartition
101 static NTSTATUS TAPE_CreatePartition( int fd, const TAPE_CREATE_PARTITION *data )
103 #ifdef HAVE_SYS_MTIO_H
104 struct mtop cmd;
106 TRACE( "fd: %d method: 0x%08x count: 0x%08x size: 0x%08x\n",
107 fd, data->Method, data->Count, data->Size );
109 if (data->Count > 1)
111 WARN( "Creating more than 1 partition is not supported\n" );
112 return STATUS_INVALID_PARAMETER;
115 switch (data->Method)
117 #ifdef MTMKPART
118 case TAPE_FIXED_PARTITIONS:
119 case TAPE_SELECT_PARTITIONS:
120 cmd.mt_op = MTMKPART;
121 cmd.mt_count = 0;
122 break;
123 case TAPE_INITIATOR_PARTITIONS:
124 cmd.mt_op = MTMKPART;
125 cmd.mt_count = data->Size;
126 break;
127 #endif
128 default:
129 ERR( "Unhandled method: 0x%08x\n", data->Method );
130 return STATUS_INVALID_PARAMETER;
133 return TAPE_GetStatus( ioctl( fd, MTIOCTOP, &cmd ) );
134 #else
135 FIXME( "Not implemented.\n" );
136 return STATUS_NOT_SUPPORTED;
137 #endif
140 /******************************************************************
141 * TAPE_Erase
143 static NTSTATUS TAPE_Erase( int fd, const TAPE_ERASE *data )
145 #ifdef HAVE_SYS_MTIO_H
146 struct mtop cmd;
148 TRACE( "fd: %d type: 0x%08x immediate: 0x%02x\n",
149 fd, data->Type, data->Immediate );
151 switch (data->Type)
153 case TAPE_ERASE_LONG:
154 cmd.mt_op = MTERASE;
155 cmd.mt_count = 1;
156 break;
157 case TAPE_ERASE_SHORT:
158 cmd.mt_op = MTERASE;
159 cmd.mt_count = 0;
160 break;
161 default:
162 ERR( "Unhandled type: 0x%08x\n", data->Type );
163 return STATUS_INVALID_PARAMETER;
166 return TAPE_GetStatus( ioctl( fd, MTIOCTOP, &cmd ) );
167 #else
168 FIXME( "Not implemented.\n" );
169 return STATUS_NOT_SUPPORTED;
170 #endif
173 /******************************************************************
174 * TAPE_GetDriveParams
176 static NTSTATUS TAPE_GetDriveParams( int fd, TAPE_GET_DRIVE_PARAMETERS *data )
178 #ifdef HAVE_SYS_MTIO_H
179 struct mtget get;
180 NTSTATUS status;
182 TRACE( "fd: %d\n", fd );
184 memset( data, 0, sizeof(TAPE_GET_DRIVE_PARAMETERS) );
186 status = TAPE_GetStatus( ioctl( fd, MTIOCGET, &get ) );
187 if (status != STATUS_SUCCESS)
188 return status;
190 data->ECC = FALSE;
191 data->Compression = FALSE;
192 data->DataPadding = FALSE;
193 data->ReportSetmarks = FALSE;
194 #ifdef HAVE_STRUCT_MTGET_MT_BLKSIZ
195 data->DefaultBlockSize = get.mt_blksiz;
196 #else
197 data->DefaultBlockSize = get.mt_dsreg & MT_ST_BLKSIZE_MASK;
198 #endif
199 data->MaximumBlockSize = data->DefaultBlockSize;
200 data->MinimumBlockSize = data->DefaultBlockSize;
201 data->MaximumPartitionCount = 1;
203 return status;
204 #else
205 FIXME( "Not implemented.\n" );
206 return STATUS_NOT_SUPPORTED;
207 #endif
210 /******************************************************************
211 * TAPE_GetMediaParams
213 static NTSTATUS TAPE_GetMediaParams( int fd, TAPE_GET_MEDIA_PARAMETERS *data )
215 #ifdef HAVE_SYS_MTIO_H
216 struct mtget get;
217 NTSTATUS status;
219 TRACE( "fd: %d\n", fd );
221 memset( data, 0, sizeof(TAPE_GET_MEDIA_PARAMETERS) );
223 status = TAPE_GetStatus( ioctl( fd, MTIOCGET, &get ) );
224 if (status != STATUS_SUCCESS)
225 return status;
227 data->Capacity.QuadPart = 1024 * 1024 * 1024;
228 data->Remaining.QuadPart = 1024 * 1024 * 1024;
229 #ifdef HAVE_STRUCT_MTGET_MT_BLKSIZ
230 data->BlockSize = get.mt_blksiz;
231 #else
232 data->BlockSize = get.mt_dsreg & MT_ST_BLKSIZE_MASK;
233 #endif
234 data->PartitionCount = 1;
235 #ifdef HAVE_STRUCT_MTGET_MT_GSTAT
236 data->WriteProtected = (GMT_WR_PROT(get.mt_gstat) != 0);
237 #else
238 data->WriteProtected = 0;
239 #endif
241 return status;
242 #else
243 FIXME( "Not implemented.\n" );
244 return STATUS_NOT_SUPPORTED;
245 #endif
248 /******************************************************************
249 * TAPE_GetPosition
251 static NTSTATUS TAPE_GetPosition( int fd, ULONG type, TAPE_GET_POSITION *data )
253 #ifdef HAVE_SYS_MTIO_H
254 struct mtget get;
255 #ifndef HAVE_STRUCT_MTGET_MT_BLKNO
256 struct mtpos pos;
257 #endif
258 NTSTATUS status;
260 TRACE( "fd: %d type: 0x%08x\n", fd, type );
262 memset( data, 0, sizeof(TAPE_GET_POSITION) );
264 status = TAPE_GetStatus( ioctl( fd, MTIOCGET, &get ) );
265 if (status != STATUS_SUCCESS)
266 return status;
268 #ifndef HAVE_STRUCT_MTGET_MT_BLKNO
269 status = TAPE_GetStatus( ioctl( fd, MTIOCPOS, &pos ) );
270 if (status != STATUS_SUCCESS)
271 return status;
272 #endif
274 switch (type)
276 case TAPE_ABSOLUTE_BLOCK:
277 data->Type = type;
278 data->Partition = get.mt_resid;
279 #ifdef HAVE_STRUCT_MTGET_MT_BLKNO
280 data->OffsetLow = get.mt_blkno;
281 #else
282 data->OffsetLow = pos.mt_blkno;
283 #endif
284 break;
285 case TAPE_LOGICAL_BLOCK:
286 case TAPE_PSEUDO_LOGICAL_BLOCK:
287 WARN( "Positioning type not supported\n" );
288 break;
289 default:
290 ERR( "Unhandled type: 0x%08x\n", type );
291 return STATUS_INVALID_PARAMETER;
294 return status;
295 #else
296 FIXME( "Not implemented.\n" );
297 return STATUS_NOT_SUPPORTED;
298 #endif
301 /******************************************************************
302 * TAPE_Prepare
304 static NTSTATUS TAPE_Prepare( int fd, const TAPE_PREPARE *data )
306 #ifdef HAVE_SYS_MTIO_H
307 struct mtop cmd;
309 TRACE( "fd: %d type: 0x%08x immediate: 0x%02x\n",
310 fd, data->Operation, data->Immediate );
312 switch (data->Operation)
314 #ifdef MTLOAD
315 case TAPE_LOAD:
316 cmd.mt_op = MTLOAD;
317 break;
318 #endif
319 #ifdef MTUNLOAD
320 case TAPE_UNLOAD:
321 cmd.mt_op = MTUNLOAD;
322 break;
323 #endif
324 #ifdef MTRETEN
325 case TAPE_TENSION:
326 cmd.mt_op = MTRETEN;
327 break;
328 #endif
329 #ifdef MTLOCK
330 case TAPE_LOCK:
331 cmd.mt_op = MTLOCK;
332 break;
333 #endif
334 #ifdef MTUNLOCK
335 case TAPE_UNLOCK:
336 cmd.mt_op = MTUNLOCK;
337 break;
338 #endif
339 case TAPE_FORMAT:
340 /* Native ignores this if the drive doesn't support it */
341 return STATUS_SUCCESS;
342 default:
343 ERR( "Unhandled operation: 0x%08x\n", data->Operation );
344 return STATUS_INVALID_PARAMETER;
347 return TAPE_GetStatus( ioctl( fd, MTIOCTOP, &cmd ) );
348 #else
349 FIXME( "Not implemented.\n" );
350 return STATUS_NOT_SUPPORTED;
351 #endif
354 /******************************************************************
355 * TAPE_SetDriveParams
357 static NTSTATUS TAPE_SetDriveParams( int fd, const TAPE_SET_DRIVE_PARAMETERS *data )
359 #if defined(HAVE_SYS_MTIO_H) && defined(MTCOMPRESSION)
360 struct mtop cmd;
362 TRACE( "fd: %d ECC: 0x%02x, compression: 0x%02x padding: 0x%02x\n",
363 fd, data->ECC, data->Compression, data->DataPadding );
364 TRACE( "setmarks: 0x%02x zonesize: 0x%08x\n",
365 data->ReportSetmarks, data->EOTWarningZoneSize );
367 if (data->ECC || data->DataPadding || data->ReportSetmarks ||
368 data->EOTWarningZoneSize ) WARN( "Setting not supported\n" );
370 cmd.mt_op = MTCOMPRESSION;
371 cmd.mt_count = data->Compression;
373 return TAPE_GetStatus( ioctl( fd, MTIOCTOP, &cmd ) );
374 #else
375 FIXME( "Not implemented.\n" );
376 return STATUS_NOT_SUPPORTED;
377 #endif
380 /******************************************************************
381 * TAPE_SetMediaParams
383 static NTSTATUS TAPE_SetMediaParams( int fd, const TAPE_SET_MEDIA_PARAMETERS *data )
385 #ifdef HAVE_SYS_MTIO_H
386 struct mtop cmd;
388 TRACE( "fd: %d blocksize: 0x%08x\n", fd, data->BlockSize );
390 cmd.mt_op = MTSETBLK;
391 cmd.mt_count = data->BlockSize;
393 return TAPE_GetStatus( ioctl( fd, MTIOCTOP, &cmd ) );
394 #else
395 FIXME( "Not implemented.\n" );
396 return STATUS_NOT_SUPPORTED;
397 #endif
400 /******************************************************************
401 * TAPE_SetPosition
403 static NTSTATUS TAPE_SetPosition( int fd, const TAPE_SET_POSITION *data )
405 #ifdef HAVE_SYS_MTIO_H
406 struct mtop cmd;
408 TRACE( "fd: %d method: 0x%08x partition: 0x%08x offset: 0x%s immediate: 0x%02x\n",
409 fd, data->Method, data->Partition, wine_dbgstr_longlong(data->Offset.QuadPart),
410 data->Immediate );
412 if (sizeof(cmd.mt_count) < sizeof(data->Offset.QuadPart) &&
413 (int)data->Offset.QuadPart != data->Offset.QuadPart)
415 ERR("Offset too large or too small\n");
416 return STATUS_INVALID_PARAMETER;
419 switch (data->Method)
421 case TAPE_REWIND:
422 cmd.mt_op = MTREW;
423 break;
424 #ifdef MTSEEK
425 case TAPE_ABSOLUTE_BLOCK:
426 cmd.mt_op = MTSEEK;
427 cmd.mt_count = data->Offset.QuadPart;
428 break;
429 #endif
430 #ifdef MTEOM
431 case TAPE_SPACE_END_OF_DATA:
432 cmd.mt_op = MTEOM;
433 break;
434 #endif
435 case TAPE_SPACE_FILEMARKS:
436 if (data->Offset.QuadPart >= 0) {
437 cmd.mt_op = MTFSF;
438 cmd.mt_count = data->Offset.QuadPart;
440 else {
441 cmd.mt_op = MTBSF;
442 cmd.mt_count = -data->Offset.QuadPart;
444 break;
445 #if defined(MTFSS) && defined(MTBSS)
446 case TAPE_SPACE_SETMARKS:
447 if (data->Offset.QuadPart >= 0) {
448 cmd.mt_op = MTFSS;
449 cmd.mt_count = data->Offset.QuadPart;
451 else {
452 cmd.mt_op = MTBSS;
453 cmd.mt_count = -data->Offset.QuadPart;
455 break;
456 #endif
457 case TAPE_LOGICAL_BLOCK:
458 case TAPE_PSEUDO_LOGICAL_BLOCK:
459 case TAPE_SPACE_RELATIVE_BLOCKS:
460 case TAPE_SPACE_SEQUENTIAL_FMKS:
461 case TAPE_SPACE_SEQUENTIAL_SMKS:
462 WARN( "Positioning method not supported\n" );
463 return STATUS_INVALID_PARAMETER;
464 default:
465 ERR( "Unhandled method: 0x%08x\n", data->Method );
466 return STATUS_INVALID_PARAMETER;
469 return TAPE_GetStatus( ioctl( fd, MTIOCTOP, &cmd ) );
470 #else
471 FIXME( "Not implemented.\n" );
472 return STATUS_NOT_SUPPORTED;
473 #endif
476 /******************************************************************
477 * TAPE_WriteMarks
479 static NTSTATUS TAPE_WriteMarks( int fd, const TAPE_WRITE_MARKS *data )
481 #ifdef HAVE_SYS_MTIO_H
482 struct mtop cmd;
484 TRACE( "fd: %d type: 0x%08x count: 0x%08x immediate: 0x%02x\n",
485 fd, data->Type, data->Count, data->Immediate );
487 switch (data->Type)
489 #ifdef MTWSM
490 case TAPE_SETMARKS:
491 cmd.mt_op = MTWSM;
492 cmd.mt_count = data->Count;
493 break;
494 #endif
495 case TAPE_FILEMARKS:
496 case TAPE_SHORT_FILEMARKS:
497 case TAPE_LONG_FILEMARKS:
498 cmd.mt_op = MTWEOF;
499 cmd.mt_count = data->Count;
500 break;
501 default:
502 ERR( "Unhandled type: 0x%08x\n", data->Type );
503 return STATUS_INVALID_PARAMETER;
506 return TAPE_GetStatus( ioctl( fd, MTIOCTOP, &cmd ) );
507 #else
508 FIXME( "Not implemented.\n" );
509 return STATUS_NOT_SUPPORTED;
510 #endif
513 /******************************************************************
514 * TAPE_DeviceIoControl
516 * SEE ALSO
517 * NtDeviceIoControl.
519 NTSTATUS TAPE_DeviceIoControl( HANDLE device, HANDLE event,
520 PIO_APC_ROUTINE apc, PVOID apc_user, PIO_STATUS_BLOCK io_status,
521 ULONG io_control, LPVOID in_buffer, DWORD in_size,
522 LPVOID out_buffer, DWORD out_size )
524 DWORD sz = 0;
525 NTSTATUS status = STATUS_INVALID_PARAMETER;
526 int fd, needs_close;
528 TRACE( "%p %s %p %d %p %d %p\n", device, io2str(io_control),
529 in_buffer, in_size, out_buffer, out_size, io_status );
531 io_status->Information = 0;
533 if ((status = server_get_unix_fd( device, 0, &fd, &needs_close, NULL, NULL )))
534 goto error;
536 switch (io_control)
538 case IOCTL_TAPE_CREATE_PARTITION:
539 status = TAPE_CreatePartition( fd, in_buffer );
540 break;
541 case IOCTL_TAPE_ERASE:
542 status = TAPE_Erase( fd, in_buffer );
543 break;
544 case IOCTL_TAPE_GET_DRIVE_PARAMS:
545 status = TAPE_GetDriveParams( fd, out_buffer );
546 break;
547 case IOCTL_TAPE_GET_MEDIA_PARAMS:
548 status = TAPE_GetMediaParams( fd, out_buffer );
549 break;
550 case IOCTL_TAPE_GET_POSITION:
551 status = TAPE_GetPosition( fd, ((TAPE_GET_POSITION *)in_buffer)->Type,
552 out_buffer );
553 break;
554 case IOCTL_TAPE_GET_STATUS:
555 status = FILE_GetNtStatus();
556 break;
557 case IOCTL_TAPE_PREPARE:
558 status = TAPE_Prepare( fd, in_buffer );
559 break;
560 case IOCTL_TAPE_SET_DRIVE_PARAMS:
561 status = TAPE_SetDriveParams( fd, in_buffer );
562 break;
563 case IOCTL_TAPE_SET_MEDIA_PARAMS:
564 status = TAPE_SetMediaParams( fd, in_buffer );
565 break;
566 case IOCTL_TAPE_SET_POSITION:
567 status = TAPE_SetPosition( fd, in_buffer );
568 break;
569 case IOCTL_TAPE_WRITE_MARKS:
570 status = TAPE_WriteMarks( fd, in_buffer );
571 break;
573 case IOCTL_TAPE_CHECK_VERIFY:
574 case IOCTL_TAPE_FIND_NEW_DEVICES:
575 break;
576 default:
577 FIXME( "Unsupported IOCTL %x (type=%x access=%x func=%x meth=%x)\n",
578 io_control, io_control >> 16, (io_control >> 14) & 3,
579 (io_control >> 2) & 0xfff, io_control & 3 );
580 break;
583 if (needs_close) close( fd );
585 error:
586 io_status->u.Status = status;
587 io_status->Information = sz;
588 if (event) NtSetEvent( event, NULL );
589 return status;