1 /* 2 vfdlink.c 3 4 Virtual Floppy Drive for Windows NT platform 5 Kernel mode driver: persistent drive letter functions 6 7 Copyright (C) 2003-2005 Ken Kato 8 */ 9 10 #include "imports.h" 11 #include "vfddrv.h" 12 #include "vfddbg.h" 13 14 #ifdef ALLOC_PRAGMA 15 #pragma alloc_text(PAGE, VfdSetLink) 16 #pragma alloc_text(PAGE, VfdLoadLink) 17 #pragma alloc_text(PAGE, VfdStoreLink) 18 #endif // ALLOC_PRAGMA 19 20 // 21 // create or remove the persistent drive letter (Windows NT) 22 // 23 NTSTATUS 24 VfdSetLink( 25 IN PDEVICE_EXTENSION DeviceExtension, 26 IN CHAR DriveLetter) 27 { 28 UNICODE_STRING unicode_name; 29 WCHAR name_buf[15]; 30 NTSTATUS status = STATUS_SUCCESS; 31 32 VFDTRACE(VFDINFO, ("[VFD] VfdSetLink - IN\n")); 33 34 // convert lower case into upper case 35 36 if (DriveLetter >= 'a' && DriveLetter <= 'z') { 37 DriveLetter -= ('a' - 'A'); 38 } 39 40 // check the drive letter range 41 42 if (DriveLetter != 0 && 43 (DriveLetter < 'A' || DriveLetter > 'Z')) { 44 return STATUS_INVALID_PARAMETER; 45 } 46 47 if (DeviceExtension->DriveLetter && 48 DeviceExtension->DriveLetter != DriveLetter) { 49 // 50 // Delete the old drive letter 51 // 52 #ifndef __REACTOS__ 53 name_buf[sizeof(name_buf) - 1] = UNICODE_NULL; 54 #else 55 name_buf[ARRAYSIZE(name_buf) - 1] = UNICODE_NULL; 56 #endif 57 58 _snwprintf(name_buf, sizeof(name_buf) - 1, 59 L"\\??\\%wc:", DeviceExtension->DriveLetter); 60 61 RtlInitUnicodeString(&unicode_name, name_buf); 62 63 status = IoDeleteSymbolicLink(&unicode_name); 64 65 if (NT_SUCCESS(status)) { 66 VFDTRACE(VFDINFO, 67 ("[VFD] Link %ws deleted\n", name_buf)); 68 69 DeviceExtension->DriveLetter = 0; 70 } 71 else if (status != STATUS_OBJECT_NAME_NOT_FOUND) { 72 // the driver letter did not exist in the first place 73 74 VFDTRACE(VFDINFO, 75 ("[VFD] Link %ws not found\n", name_buf)); 76 77 DeviceExtension->DriveLetter = 0; 78 status = STATUS_SUCCESS; 79 } 80 else { 81 VFDTRACE(VFDWARN, 82 ("[VFD] IoDeleteSymbolicLink %ws - %s\n", 83 name_buf, GetStatusName(status))); 84 } 85 } 86 87 if (NT_SUCCESS(status) && DriveLetter) { 88 // 89 // Create a new drive letter 90 // 91 92 #ifndef __REACTOS__ 93 name_buf[sizeof(name_buf) - 1] = UNICODE_NULL; 94 95 _snwprintf(name_buf, sizeof(name_buf) - 1, 96 (OsMajorVersion >= 5) ? 97 L"\\??\\Global\\%wc:" : L"\\??\\%wc:", 98 DriveLetter); 99 #else 100 name_buf[ARRAYSIZE(name_buf) - 1] = UNICODE_NULL; 101 102 _snwprintf(name_buf, ARRAYSIZE(name_buf) - 1, 103 (OsMajorVersion >= 5) ? 104 L"\\??\\Global\\%wc:" : L"\\??\\%wc:", 105 DriveLetter); 106 #endif 107 108 RtlInitUnicodeString(&unicode_name, name_buf); 109 110 status = IoCreateSymbolicLink( 111 &unicode_name, &(DeviceExtension->DeviceName)); 112 113 if (NT_SUCCESS(status)) { 114 VFDTRACE(VFDINFO, ("[VFD] Link %ws created\n", name_buf)); 115 116 DeviceExtension->DriveLetter = DriveLetter; 117 } 118 else { 119 VFDTRACE(VFDWARN, 120 ("[VFD] IoCreateSymbolicLink %ws - %s\n", 121 name_buf, GetStatusName(status))); 122 } 123 } 124 125 VFDTRACE(VFDINFO, 126 ("[VFD] VfdSetLink - %s\n", GetStatusName(status))); 127 128 return status; 129 } 130 131 // 132 // load the persistent drive letter from the registry 133 // 134 NTSTATUS 135 VfdLoadLink( 136 IN PDEVICE_EXTENSION DeviceExtension, 137 IN PWSTR RegistryPath) 138 { 139 RTL_QUERY_REGISTRY_TABLE params[2]; 140 WCHAR name_buf[20]; 141 ULONG letter; 142 ULONG zero = 0; 143 NTSTATUS status; 144 145 VFDTRACE(VFDINFO, ("[VFD] VfdLoadLink - IN\n")); 146 147 RtlZeroMemory(params, sizeof(params)); 148 149 #ifndef __REACTOS__ 150 name_buf[sizeof(name_buf) - 1] = UNICODE_NULL; 151 152 _snwprintf(name_buf, sizeof(name_buf) - 1, 153 VFD_REG_DRIVE_LETTER L"%lu", 154 DeviceExtension->DeviceNumber); 155 #else 156 name_buf[ARRAYSIZE(name_buf) - 1] = UNICODE_NULL; 157 158 _snwprintf(name_buf, ARRAYSIZE(name_buf) - 1, 159 VFD_REG_DRIVE_LETTER L"%lu", 160 DeviceExtension->DeviceNumber); 161 #endif 162 163 params[0].Flags = RTL_QUERY_REGISTRY_DIRECT; 164 params[0].Name = name_buf; 165 params[0].EntryContext = &letter; 166 params[0].DefaultType = REG_DWORD; 167 params[0].DefaultData = &zero; 168 params[0].DefaultLength = sizeof(ULONG); 169 170 status = RtlQueryRegistryValues( 171 RTL_REGISTRY_ABSOLUTE | RTL_REGISTRY_OPTIONAL, 172 RegistryPath, ¶ms[0], NULL, NULL); 173 174 VFDTRACE(VFDINFO, 175 ("[VFD] Drive letter '%wc' loaded from the registry\n", 176 letter ? letter : ' ')); 177 178 DeviceExtension->DriveLetter = (CHAR)letter; 179 180 VFDTRACE(VFDINFO, 181 ("[VFD] VfdLoadLink - %s\n", GetStatusName(status))); 182 183 return status; 184 } 185 186 // 187 // store the persistent drive letter into the registry 188 // 189 NTSTATUS 190 VfdStoreLink( 191 IN PDEVICE_EXTENSION DeviceExtension) 192 { 193 PVFD_DRIVER_EXTENSION driver_extension; 194 WCHAR name_buf[20]; 195 ULONG letter; 196 NTSTATUS status; 197 198 VFDTRACE(VFDINFO, ("[VFD] VfdStoreLink - IN\n")); 199 200 #ifdef VFD_PNP 201 driver_extension = IoGetDriverObjectExtension( 202 DeviceExtension->device_object->DriverObject, 203 VFD_DRIVER_EXTENSION_ID); 204 #else // VFD_PNP 205 driver_extension = DeviceExtension->DriverExtension; 206 #endif // VFD_PNP 207 208 if (!driver_extension || 209 !driver_extension->RegistryPath.Buffer) { 210 211 VFDTRACE(VFDWARN, ("[VFD] Registry Path not present.\n")); 212 VFDTRACE(VFDINFO, ("[VFD] VfdStoreLinks - OUT\n")); 213 return STATUS_DRIVER_INTERNAL_ERROR; 214 } 215 216 #ifndef __REACTOS__ 217 name_buf[sizeof(name_buf) - 1] = UNICODE_NULL; 218 219 _snwprintf(name_buf, sizeof(name_buf) - 1, 220 VFD_REG_DRIVE_LETTER L"%lu", 221 DeviceExtension->DeviceNumber); 222 #else 223 name_buf[ARRAYSIZE(name_buf) - 1] = UNICODE_NULL; 224 225 _snwprintf(name_buf, ARRAYSIZE(name_buf) - 1, 226 VFD_REG_DRIVE_LETTER L"%lu", 227 DeviceExtension->DeviceNumber); 228 #endif 229 230 letter = DeviceExtension->DriveLetter; 231 232 status = RtlWriteRegistryValue( 233 RTL_REGISTRY_ABSOLUTE, 234 driver_extension->RegistryPath.Buffer, 235 name_buf, 236 REG_DWORD, 237 &letter, 238 sizeof(ULONG)); 239 240 if (!NT_SUCCESS(status)) { 241 VFDTRACE(VFDWARN, 242 ("[VFD] RtlWriteRegistryValue - %s\n", 243 GetStatusName(status))); 244 } 245 else { 246 VFDTRACE(VFDINFO, 247 ("[VFD] Drive letter '%wc' stored into the registry\n", 248 letter ? letter : L' ')); 249 } 250 251 VFDTRACE(VFDINFO, 252 ("[VFD] VfdStoreLink - %s\n", GetStatusName(status))); 253 254 return status; 255 } 256