47bff1c3896da609e3e312b5639ca94cc9ec58cd
[AROS.git] / rom / dos / errorreport.c
blob47bff1c3896da609e3e312b5639ca94cc9ec58cd
1 /*
2 Copyright © 1995-2011, The AROS Development Team. All rights reserved.
3 $Id$
5 Desc:
6 Lang: English
7 */
9 #include <dos/dos.h>
10 #include <dos/dosextens.h>
11 #include <intuition/intuition.h>
12 #include <exec/ports.h>
13 #include <aros/debug.h>
15 #define CATCOMP_NUMBERS
17 #include "dos_intern.h"
18 #include "strings.h"
20 /*****************************************************************************
22 NAME */
23 #include <proto/dos.h>
25 AROS_LH4(BOOL, ErrorReport,
27 /* SYNOPSIS */
28 AROS_LHA(LONG , code , D1),
29 AROS_LHA(LONG , type , D2),
30 AROS_LHA(IPTR , arg1 , D3),
31 AROS_LHA(struct MsgPort *, device, D4),
33 /* LOCATION */
34 struct DosLibrary *, DOSBase, 80, Dos)
36 /* FUNCTION
37 Displays a requester with Retry/Cancel buttons for an error.
38 IoErr() is set to "code".
40 INPUTS
42 code -- The error to put up the requester for
43 type -- Type of request
45 REPORT_LOCK -- arg1 is a lock (BPTR).
46 REPORT_FH -- arg1 is a filehandle (BPTR).
47 REPORT_VOLUME -- arg1 is a volumenode (C pointer).
48 REPORT_INSERT -- arg1 is the string for the volumename
50 arg1 -- Argument according to type (see above)
51 device -- Optional handler task address (obsolete!)
53 RESULT
54 DOSFALSE - user has selected "Retry"
55 DOSTRUE - user has selected "Cancel" or code wasn't understood or
56 pr_WindowPtr is -1 or if an attempt to open the requester fails.
58 NOTES
60 EXAMPLE
62 BUGS
64 SEE ALSO
66 INTERNALS
68 *****************************************************************************/
70 AROS_LIBFUNC_INIT
72 struct Process *me = (struct Process *) FindTask(NULL);
73 STRPTR format;
74 BOOL want_volume = FALSE;
75 BOOL want_device = FALSE;
76 STRPTR volname = NULL;
77 STRPTR devname = NULL;
78 struct DeviceList *dl = NULL;
79 char buf[128];
80 struct DevProc *dvp;
81 struct DosList *dol;
82 APTR args[2];
83 ULONG idcmp = 0;
84 LONG err;
85 LONG res;
86 struct MsgPort *msgport;
87 struct PacketHelperStruct phs;
89 ASSERT_VALID_PROCESS(me);
91 /* do nothing if errors are disabled */
92 if (me->pr_WindowPtr == (APTR) -1) {
93 SetIoErr(code);
94 return DOSTRUE;
96 buf[0] = 0;
98 /* first setup the error format and work out which args we need */
99 switch (code) {
100 /* Volume FOO: is not validated */
101 case ERROR_DISK_NOT_VALIDATED:
102 format = DosGetString(MSG_STRING_DISK_NOT_VALIDATED);
103 want_volume = TRUE;
104 break;
106 /* Volume FOO: is write protected */
107 case ERROR_DISK_WRITE_PROTECTED:
108 format = DosGetString(MSG_STRING_DISK_WRITE_PROTECTED);
109 want_volume = TRUE;
110 break;
112 /* Please (insert|replace) volume FOO: in ... */
113 case ERROR_DEVICE_NOT_MOUNTED:
114 if (type == REPORT_INSERT) {
115 format = DosGetString(MSG_STRING_DEVICE_NOT_MOUNTED_INSERT);
116 want_volume = TRUE;
118 else if (type == REPORT_STREAM) {
119 format = DosGetString(MSG_STRING_DEVICE_NOT_MOUNTED_REPLACE_TARGET);
120 want_volume = want_device = TRUE;
122 else {
123 format = DosGetString(MSG_STRING_DEVICE_NOT_MOUNTED_REPLACE);
124 want_volume = TRUE;
126 idcmp = IDCMP_DISKINSERTED;
127 break;
129 /* Volume FOO: is full */
130 case ERROR_DISK_FULL:
131 format = DosGetString(MSG_STRING_DISK_FULL);
132 want_volume = TRUE;
133 break;
135 /* Not a DOS disk in ...*/
136 case ERROR_NOT_A_DOS_DISK:
137 format = DosGetString(MSG_STRING_NOT_A_DOS_DISK);
138 want_device = TRUE;
139 break;
141 /* No disk present in ...*/
142 case ERROR_NO_DISK:
143 format = DosGetString(MSG_STRING_NO_DISK);
144 want_device = TRUE;
145 break;
147 /* You MUST replace volume FOO: in ... */
148 case ABORT_BUSY:
149 format = DosGetString(MSG_STRING_ABORT_BUSY);
150 want_volume = want_device = TRUE;
151 idcmp = IDCMP_DISKINSERTED;
152 break;
154 /* Volume FOO: has a read/write error */
155 case ABORT_DISK_ERROR:
156 format = DosGetString(MSG_STRING_ABORT_DISK_ERROR);
157 want_volume = TRUE;
158 break;
160 /* do nothing with other errors */
161 default:
162 return DOSTRUE;
165 /* now we need to determine the volume name. if they gave it to use
166 * (REPORT_INSERT), we just use it. otherwise, we get it from the device
167 * list (REPORT_VOLUME). if we don't have one, we use the handler/unit
168 * pair to find it */
169 switch (type) {
170 /* a filehandle */
171 case REPORT_STREAM:
172 if (arg1 == (IPTR)NULL)
173 return DOSTRUE;
174 msgport = ((struct FileHandle *) BADDR(arg1))->fh_Type;
175 dl = (struct DeviceList*)BADDR(dopacket1(DOSBase, NULL, msgport, ACTION_CURRENT_VOLUME, ((struct FileHandle *) BADDR(arg1))->fh_Arg1));
176 if (dl)
177 volname = (char*)BADDR(dl->dl_Name) + 1;
178 break;
180 case REPORT_TASK:
181 /* XXX what is this? */
182 return DOSTRUE;
184 /* a lock */
185 case REPORT_LOCK:
187 struct FileInfoBlock *fib = AllocDosObject(DOS_FIB, 0);
188 if (!fib)
189 return DOSTRUE;
190 /* if they provided a lock, just use it */
191 if (arg1 != (IPTR)NULL) {
192 msgport = ((struct FileLock *) BADDR(arg1))->fl_Task;
193 } else {
194 msgport = device;
196 if (dopacket2(DOSBase, NULL, msgport, ACTION_EXAMINE_OBJECT, arg1, (SIPTR)MKBADDR(fib))) {
197 fixfib(fib);
198 strncpy(buf, fib->fib_FileName, sizeof (buf) - 1);
199 buf[sizeof(buf) - 1] = 0;
201 FreeDosObject(DOS_FIB, fib);
202 if (buf[0] == 0)
203 return DOSTRUE;
204 volname = buf;
206 break;
208 /* a volume, ie a DeviceList */
209 case REPORT_VOLUME:
210 if (arg1 == (IPTR)NULL)
211 return DOSTRUE;
213 dl = (struct DeviceList *) arg1;
214 volname = (char*)BADDR(dl->dl_Name) + 1;
215 msgport = dl->dl_Task;
216 break;
218 /* raw volume name */
219 case REPORT_INSERT:
220 if (arg1 == (IPTR)NULL)
221 return DOSTRUE;
222 if (!getpacketinfo(DOSBase, (STRPTR)arg1, &phs))
223 return DOSTRUE;
224 msgport = phs.port;
225 volname = (STRPTR) arg1;
226 /* rip off any trailing stuff, if its there */
227 if (SplitName(volname, ':', buf, 0, sizeof(buf)-1) == -1)
228 volname = buf;
229 freepacketinfo(DOSBase, &phs);
230 break;
232 /* do nothing with other types */
233 default:
234 return DOSTRUE;
237 /* for the device name we need the doslist entry */
238 if (want_device) {
239 /* XXX for packets we just search the doslist for a DLT_DEVICE with
240 * the same task pointer. no need to worry about multiple units */
242 /* remember the current error in case we have to bail out */
243 err = IoErr();
245 /* get the entry for the volume */
246 if ((dvp = GetDeviceProc(volname, NULL)) == NULL) {
247 SetIoErr(err);
248 return DOSTRUE;
251 /* search the list for a device node with the same port as the volume */
252 dol = LockDosList(LDF_READ | LDF_ALL);
253 while (dol != NULL && (dol->dol_Type != DLT_DEVICE || dol->dol_Task != msgport))
254 dol = BADDR(dol->dol_Next);
256 /* found it */
257 if (dol != NULL)
258 devname = (char*)dol->dol_Name + 1;
260 /* XXX can this happen? */
261 else
262 devname = "???";
264 UnLockDosList(LDF_READ | LDF_ALL);
266 FreeDeviceProc(dvp);
269 /* have all we need, now to build the arg array */
270 if (want_volume) {
271 args[0] = volname;
272 if (want_device)
273 args[1] = devname;
275 else if (want_device)
276 args[0] = devname;
278 /* display it. idcmp is set further up to catch "disk insert" events if
279 * we're waiting for them to insert something */
281 res = DisplayError(format, idcmp, &args);
283 SetIoErr(code);
285 return res == 0 ? DOSFALSE : DOSTRUE;
287 AROS_LIBFUNC_EXIT
288 } /* ErrorReport */