:pserver:cvsanon@mok.lvcm.com:/CVS/ReactOS reactos
[reactos.git] / ntoskrnl / io / arcname.c
1 /*
2  *  ReactOS kernel
3  *  Copyright (C) 2002 ReactOS Team
4  *
5  *  This program is free software; you can redistribute it and/or modify
6  *  it under the terms of the GNU General Public License as published by
7  *  the Free Software Foundation; either version 2 of the License, or
8  *  (at your option) any later version.
9  *
10  *  This program is distributed in the hope that it will be useful,
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  *  GNU General Public License for more details.
14  *
15  *  You should have received a copy of the GNU General Public License
16  *  along with this program; if not, write to the Free Software
17  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18  */
19 /* $Id$
20  *
21  * COPYRIGHT:       See COPYING in the top level directory
22  * PROJECT:         ReactOS kernel
23  * FILE:            ntoskrnl/io/arcname.c
24  * PURPOSE:         creates ARC names for boot devices
25  * PROGRAMMER:      Eric Kohl (ekohl@rz-online.de)
26  */
27
28
29 /* INCLUDES *****************************************************************/
30
31 #include <ddk/ntddk.h>
32
33 #include "internal/io.h"
34 #include "internal/xhal.h"
35
36 #define NDEBUG
37 #include <internal/debug.h>
38
39 /* MACROS *******************************************************************/
40
41 #define FS_VOLUME_BUFFER_SIZE (MAX_PATH + sizeof(FILE_FS_VOLUME_INFORMATION))
42
43 /* FUNCTIONS ****************************************************************/
44
45 NTSTATUS
46 IoCreateArcNames(VOID)
47 {
48   PCONFIGURATION_INFORMATION ConfigInfo;
49   PDRIVE_LAYOUT_INFORMATION LayoutInfo = NULL;
50   WCHAR DeviceNameBuffer[80];
51   WCHAR ArcNameBuffer[80];
52   UNICODE_STRING DeviceName;
53   UNICODE_STRING ArcName;
54   ULONG i, j;
55   NTSTATUS Status;
56
57   DPRINT("IoCreateArcNames() called\n");
58
59   ConfigInfo = IoGetConfigurationInformation();
60
61   /* create ARC names for floppy drives */
62   DPRINT("Floppy drives: %lu\n", ConfigInfo->FloppyCount);
63   for (i = 0; i < ConfigInfo->FloppyCount; i++)
64     {
65       swprintf(DeviceNameBuffer,
66                L"\\Device\\Floppy%lu",
67                i);
68       RtlInitUnicodeString(&DeviceName,
69                            DeviceNameBuffer);
70
71       swprintf(ArcNameBuffer,
72                L"\\ArcName\\multi(0)disk(0)fdisk(%lu)",
73                i);
74       RtlInitUnicodeString(&ArcName,
75                            ArcNameBuffer);
76       DPRINT("%wZ ==> %wZ\n",
77              &ArcName,
78              &DeviceName);
79
80       Status = IoAssignArcName(&ArcName,
81                                &DeviceName);
82       if (!NT_SUCCESS(Status))
83         return(Status);
84     }
85
86   /* create ARC names for hard disk drives */
87   DPRINT("Disk drives: %lu\n", ConfigInfo->DiskCount);
88   for (i = 0; i < ConfigInfo->DiskCount; i++)
89     {
90       swprintf(DeviceNameBuffer,
91                L"\\Device\\Harddisk%lu\\Partition0",
92                i);
93       RtlInitUnicodeString(&DeviceName,
94                            DeviceNameBuffer);
95
96       swprintf(ArcNameBuffer,
97                L"\\ArcName\\multi(0)disk(0)rdisk(%lu)partition(0)",
98                i);
99       RtlInitUnicodeString(&ArcName,
100                            ArcNameBuffer);
101       DPRINT("%wZ ==> %wZ\n",
102              &ArcName,
103              &DeviceName);
104
105       Status = IoAssignArcName(&ArcName,
106                                &DeviceName);
107       if (!NT_SUCCESS(Status))
108         return(Status);
109
110       Status = xHalQueryDriveLayout(&DeviceName,
111                                     &LayoutInfo);
112       if (!NT_SUCCESS(Status))
113         return(Status);
114
115       DPRINT("Number of partitions: %u\n", LayoutInfo->PartitionCount);
116
117       for (j = 0;j < LayoutInfo->PartitionCount; j++)
118         {
119           swprintf(DeviceNameBuffer,
120                    L"\\Device\\Harddisk%lu\\Partition%lu",
121                    i,
122                    j + 1);
123           RtlInitUnicodeString(&DeviceName,
124                                DeviceNameBuffer);
125
126           swprintf(ArcNameBuffer,
127                    L"\\ArcName\\multi(0)disk(0)rdisk(%lu)partition(%lu)",
128                    i,
129                    j + 1);
130           RtlInitUnicodeString(&ArcName,
131                                ArcNameBuffer);
132           DPRINT("%wZ ==> %wZ\n",
133                  &ArcName,
134                  &DeviceName);
135
136           Status = IoAssignArcName(&ArcName,
137                                    &DeviceName);
138           if (!NT_SUCCESS(Status))
139             return(Status);
140         }
141
142       ExFreePool(LayoutInfo);
143       LayoutInfo = NULL;
144     }
145
146   /* create ARC names for cdrom drives */
147   DPRINT("CD-ROM drives: %lu\n", ConfigInfo->CDRomCount);
148   for (i = 0; i < ConfigInfo->CDRomCount; i++)
149     {
150       swprintf(DeviceNameBuffer,
151                L"\\Device\\CdRom%lu",
152                i);
153       RtlInitUnicodeString(&DeviceName,
154                            DeviceNameBuffer);
155
156       swprintf(ArcNameBuffer,
157                L"\\ArcName\\multi(0)disk(0)cdrom(%lu)",
158                i);
159       RtlInitUnicodeString(&ArcName,
160                            ArcNameBuffer);
161       DPRINT("%wZ ==> %wZ\n",
162              &ArcName,
163              &DeviceName);
164
165       Status = IoAssignArcName(&ArcName,
166                                &DeviceName);
167       if (!NT_SUCCESS(Status))
168         return(Status);
169     }
170
171   DPRINT("IoCreateArcNames() done\n");
172
173   return(STATUS_SUCCESS);
174 }
175
176
177 static NTSTATUS
178 IopCheckCdromDevices(PULONG DeviceNumber)
179 {
180   PFILE_FS_VOLUME_INFORMATION FileFsVolume;
181   PCONFIGURATION_INFORMATION ConfigInfo;
182   OBJECT_ATTRIBUTES ObjectAttributes;
183   UNICODE_STRING DeviceName;
184   WCHAR DeviceNameBuffer[32];
185   HANDLE Handle;
186   ULONG i;
187   NTSTATUS Status;
188   IO_STATUS_BLOCK IoStatusBlock;
189   USHORT Buffer[FS_VOLUME_BUFFER_SIZE];
190
191   FileFsVolume = (PFILE_FS_VOLUME_INFORMATION)Buffer;
192
193   ConfigInfo = IoGetConfigurationInformation();
194   for (i = 0; i < ConfigInfo->CDRomCount; i++)
195     {
196       swprintf(DeviceNameBuffer,
197                L"\\Device\\CdRom%lu\\",
198                i);
199       RtlInitUnicodeString(&DeviceName,
200                            DeviceNameBuffer);
201
202       InitializeObjectAttributes(&ObjectAttributes,
203                                  &DeviceName,
204                                  0,
205                                  NULL,
206                                  NULL);
207
208       Status = NtOpenFile(&Handle,
209                           FILE_ALL_ACCESS,
210                           &ObjectAttributes,
211                           NULL,
212                           0,
213                           0);
214       DPRINT("NtOpenFile()  DeviceNumber %lu  Status %lx\n", i, Status);
215       if (NT_SUCCESS(Status))
216         {
217           Status = NtQueryVolumeInformationFile(Handle,
218                                                 &IoStatusBlock,
219                                                 FileFsVolume,
220                                                 FS_VOLUME_BUFFER_SIZE,
221                                                 FileFsVolumeInformation);
222           DPRINT("NtQueryVolumeInformationFile()  Status %lx\n", Status);
223           if (NT_SUCCESS(Status))
224             {
225               DPRINT("VolumeLabel: '%S'\n", FileFsVolume->VolumeLabel);
226               if (_wcsicmp(FileFsVolume->VolumeLabel, L"REACTOS") == 0)
227                 {
228                   NtClose(Handle);
229                   *DeviceNumber = i;
230                   return(STATUS_SUCCESS);
231                 }
232             }
233           NtClose(Handle);
234         }
235     }
236
237   *DeviceNumber = (ULONG)-1;
238
239   return(STATUS_UNSUCCESSFUL);
240 }
241
242
243 NTSTATUS
244 IoCreateSystemRootLink(PCHAR ParameterLine)
245 {
246   OBJECT_ATTRIBUTES ObjectAttributes;
247   UNICODE_STRING LinkName;
248   UNICODE_STRING DeviceName;
249   UNICODE_STRING ArcName;
250   UNICODE_STRING BootPath;
251   PCHAR ParamBuffer;
252   PWCHAR ArcNameBuffer;
253   PCHAR p;
254   NTSTATUS Status;
255   ULONG Length;
256   HANDLE Handle;
257
258   /* Create local parameter line copy */
259   ParamBuffer = ExAllocatePool(PagedPool, 256);
260   strcpy(ParamBuffer, (char *)ParameterLine);
261
262   DPRINT("%s\n", ParamBuffer);
263   /* Format: <arc_name>\<path> [options...] */
264
265   /* cut options off */
266   p = strchr(ParamBuffer, ' ');
267   if (p)
268     *p = 0;
269   DPRINT("%s\n", ParamBuffer);
270
271   /* extract path */
272   p = strchr(ParamBuffer, '\\');
273   if (p)
274     {
275       DPRINT("Boot path: %s\n", p);
276       RtlCreateUnicodeStringFromAsciiz(&BootPath, p);
277       *p = 0;
278     }
279   else
280     {
281       DPRINT("Boot path: %s\n", "\\");
282       RtlCreateUnicodeStringFromAsciiz(&BootPath, "\\");
283     }
284   DPRINT("ARC name: %s\n", ParamBuffer);
285
286   p = strstr(ParamBuffer, "cdrom");
287   if (p != NULL)
288     {
289       ULONG DeviceNumber;
290
291       DPRINT("Booting from CD-ROM!\n");
292       Status = IopCheckCdromDevices(&DeviceNumber);
293       if (!NT_SUCCESS(Status))
294         {
295           CPRINT("Failed to find setup disk!\n");
296           return(Status);
297         }
298
299       sprintf(p, "cdrom(%lu)", DeviceNumber);
300
301       DPRINT("New ARC name: %s\n", ParamBuffer);
302
303       /* Adjust original command line */
304       p = strstr(ParameterLine, "cdrom");
305       if (p != NULL);
306         {
307           char temp[256];
308           char *q;
309
310           q = strchr(p, ')');
311           if (q != NULL)
312             {
313
314               q++;
315               strcpy(temp, q);
316               sprintf(p, "cdrom(%lu)", DeviceNumber);
317               strcat(p, temp);
318             }
319         }
320     }
321
322   /* Only arc name left - build full arc name */
323   ArcNameBuffer = ExAllocatePool(PagedPool, 256 * sizeof(WCHAR));
324   swprintf(ArcNameBuffer,
325            L"\\ArcName\\%S", ParamBuffer);
326   RtlInitUnicodeString(&ArcName, ArcNameBuffer);
327   DPRINT("Arc name: %wZ\n", &ArcName);
328
329   /* free ParamBuffer */
330   ExFreePool(ParamBuffer);
331
332   /* allocate device name string */
333   DeviceName.Length = 0;
334   DeviceName.MaximumLength = 256 * sizeof(WCHAR);
335   DeviceName.Buffer = ExAllocatePool(PagedPool, 256 * sizeof(WCHAR));
336
337   InitializeObjectAttributes(&ObjectAttributes,
338                              &ArcName,
339                              OBJ_OPENLINK,
340                              NULL,
341                              NULL);
342
343   Status = NtOpenSymbolicLinkObject(&Handle,
344                                     SYMBOLIC_LINK_ALL_ACCESS,
345                                     &ObjectAttributes);
346   if (!NT_SUCCESS(Status))
347     {
348       RtlFreeUnicodeString(&BootPath);
349       RtlFreeUnicodeString(&DeviceName);
350       CPRINT("NtOpenSymbolicLinkObject() '%wZ' failed (Status %x)\n",
351              &ArcName,
352              Status);
353       RtlFreeUnicodeString(&ArcName);
354
355       return(Status);
356     }
357   RtlFreeUnicodeString(&ArcName);
358
359   Status = NtQuerySymbolicLinkObject(Handle,
360                                      &DeviceName,
361                                      &Length);
362   NtClose (Handle);
363   if (!NT_SUCCESS(Status))
364     {
365       RtlFreeUnicodeString(&BootPath);
366       RtlFreeUnicodeString(&DeviceName);
367       CPRINT("NtQuerySymbolicObject() failed (Status %x)\n",
368              Status);
369
370       return(Status);
371     }
372   DPRINT("Length: %lu DeviceName: %wZ\n", Length, &DeviceName);
373
374   RtlAppendUnicodeStringToString(&DeviceName,
375                                  &BootPath);
376
377   RtlFreeUnicodeString(&BootPath);
378   DPRINT("DeviceName: %wZ\n", &DeviceName);
379
380   /* create the '\SystemRoot' link */
381   RtlInitUnicodeStringFromLiteral(&LinkName,
382                        L"\\SystemRoot");
383
384   Status = IoCreateSymbolicLink(&LinkName,
385                                 &DeviceName);
386   RtlFreeUnicodeString (&DeviceName);
387   if (!NT_SUCCESS(Status))
388     {
389       CPRINT("IoCreateSymbolicLink() failed (Status %x)\n",
390              Status);
391
392       return(Status);
393     }
394
395   /* Check whether '\SystemRoot'(LinkName) can be opened */
396   InitializeObjectAttributes(&ObjectAttributes,
397                              &LinkName,
398                              0,
399                              NULL,
400                              NULL);
401
402   Status = NtOpenFile(&Handle,
403                       FILE_ALL_ACCESS,
404                       &ObjectAttributes,
405                       NULL,
406                       0,
407                       0);
408   if (!NT_SUCCESS(Status))
409     {
410       CPRINT("NtOpenFile() failed to open '\\SystemRoot' (Status %x)\n",
411              Status);
412       return(Status);
413     }
414
415   NtClose(Handle);
416
417   return(STATUS_SUCCESS);
418 }
419
420 /* EOF */