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 name_buf[sizeof(name_buf) - 1] = UNICODE_NULL; 53 54 _snwprintf(name_buf, sizeof(name_buf) - 1, 55 L"\\??\\%wc:", DeviceExtension->DriveLetter); 56 57 RtlInitUnicodeString(&unicode_name, name_buf); 58 59 status = IoDeleteSymbolicLink(&unicode_name); 60 61 if (NT_SUCCESS(status)) { 62 VFDTRACE(VFDINFO, 63 ("[VFD] Link %ws deleted\n", name_buf)); 64 65 DeviceExtension->DriveLetter = 0; 66 } 67 else if (status != STATUS_OBJECT_NAME_NOT_FOUND) { 68 // the driver letter did not exist in the first place 69 70 VFDTRACE(VFDINFO, 71 ("[VFD] Link %ws not found\n", name_buf)); 72 73 DeviceExtension->DriveLetter = 0; 74 status = STATUS_SUCCESS; 75 } 76 else { 77 VFDTRACE(VFDWARN, 78 ("[VFD] IoDeleteSymbolicLink %ws - %s\n", 79 name_buf, GetStatusName(status))); 80 } 81 } 82 83 if (NT_SUCCESS(status) && DriveLetter) { 84 // 85 // Create a new drive letter 86 // 87 88 name_buf[sizeof(name_buf) - 1] = UNICODE_NULL; 89 90 _snwprintf(name_buf, sizeof(name_buf) - 1, 91 (OsMajorVersion >= 5) ? 92 L"\\??\\Global\\%wc:" : L"\\??\\%wc:", 93 DriveLetter); 94 95 RtlInitUnicodeString(&unicode_name, name_buf); 96 97 status = IoCreateSymbolicLink( 98 &unicode_name, &(DeviceExtension->DeviceName)); 99 100 if (NT_SUCCESS(status)) { 101 VFDTRACE(VFDINFO, ("[VFD] Link %ws created\n", name_buf)); 102 103 DeviceExtension->DriveLetter = DriveLetter; 104 } 105 else { 106 VFDTRACE(VFDWARN, 107 ("[VFD] IoCreateSymbolicLink %ws - %s\n", 108 name_buf, GetStatusName(status))); 109 } 110 } 111 112 VFDTRACE(VFDINFO, 113 ("[VFD] VfdSetLink - %s\n", GetStatusName(status))); 114 115 return status; 116 } 117 118 // 119 // load the persistent drive letter from the registry 120 // 121 NTSTATUS 122 VfdLoadLink( 123 IN PDEVICE_EXTENSION DeviceExtension, 124 IN PWSTR RegistryPath) 125 { 126 RTL_QUERY_REGISTRY_TABLE params[2]; 127 WCHAR name_buf[20]; 128 ULONG letter; 129 ULONG zero = 0; 130 NTSTATUS status; 131 132 VFDTRACE(VFDINFO, ("[VFD] VfdLoadLink - IN\n")); 133 134 RtlZeroMemory(params, sizeof(params)); 135 136 name_buf[sizeof(name_buf) - 1] = UNICODE_NULL; 137 138 _snwprintf(name_buf, sizeof(name_buf) - 1, 139 VFD_REG_DRIVE_LETTER L"%lu", 140 DeviceExtension->DeviceNumber); 141 142 params[0].Flags = RTL_QUERY_REGISTRY_DIRECT; 143 params[0].Name = name_buf; 144 params[0].EntryContext = &letter; 145 params[0].DefaultType = REG_DWORD; 146 params[0].DefaultData = &zero; 147 params[0].DefaultLength = sizeof(ULONG); 148 149 status = RtlQueryRegistryValues( 150 RTL_REGISTRY_ABSOLUTE | RTL_REGISTRY_OPTIONAL, 151 RegistryPath, ¶ms[0], NULL, NULL); 152 153 VFDTRACE(VFDINFO, 154 ("[VFD] Drive letter '%wc' loaded from the registry\n", 155 letter ? letter : ' ')); 156 157 DeviceExtension->DriveLetter = (CHAR)letter; 158 159 VFDTRACE(VFDINFO, 160 ("[VFD] VfdLoadLink - %s\n", GetStatusName(status))); 161 162 return status; 163 } 164 165 // 166 // store the persistent drive letter into the registry 167 // 168 NTSTATUS 169 VfdStoreLink( 170 IN PDEVICE_EXTENSION DeviceExtension) 171 { 172 PVFD_DRIVER_EXTENSION driver_extension; 173 WCHAR name_buf[20]; 174 ULONG letter; 175 NTSTATUS status; 176 177 VFDTRACE(VFDINFO, ("[VFD] VfdStoreLink - IN\n")); 178 179 #ifdef VFD_PNP 180 driver_extension = IoGetDriverObjectExtension( 181 DeviceExtension->device_object->DriverObject, 182 VFD_DRIVER_EXTENSION_ID); 183 #else // VFD_PNP 184 driver_extension = DeviceExtension->DriverExtension; 185 #endif // VFD_PNP 186 187 if (!driver_extension || 188 !driver_extension->RegistryPath.Buffer) { 189 190 VFDTRACE(VFDWARN, ("[VFD] Registry Path not present.\n")); 191 VFDTRACE(VFDINFO, ("[VFD] VfdStoreLinks - OUT\n")); 192 return STATUS_DRIVER_INTERNAL_ERROR; 193 } 194 195 name_buf[sizeof(name_buf) - 1] = UNICODE_NULL; 196 197 _snwprintf(name_buf, sizeof(name_buf) - 1, 198 VFD_REG_DRIVE_LETTER L"%lu", 199 DeviceExtension->DeviceNumber); 200 201 letter = DeviceExtension->DriveLetter; 202 203 status = RtlWriteRegistryValue( 204 RTL_REGISTRY_ABSOLUTE, 205 driver_extension->RegistryPath.Buffer, 206 name_buf, 207 REG_DWORD, 208 &letter, 209 sizeof(ULONG)); 210 211 if (!NT_SUCCESS(status)) { 212 VFDTRACE(VFDWARN, 213 ("[VFD] RtlWriteRegistryValue - %s\n", 214 GetStatusName(status))); 215 } 216 else { 217 VFDTRACE(VFDINFO, 218 ("[VFD] Drive letter '%wc' stored into the registry\n", 219 letter ? letter : L' ')); 220 } 221 222 VFDTRACE(VFDINFO, 223 ("[VFD] VfdStoreLink - %s\n", GetStatusName(status))); 224 225 return status; 226 } 227