Reactos
at master 533 lines 11 kB view raw
1/* 2 * COPYRIGHT: See COPYRIGHT.TXT 3 * PROJECT: Ext2 File System Driver for WinNT/2K/XP 4 * FILE: misc.c 5 * PROGRAMMER: Matt Wu <mattwu@163.com> 6 * HOMEPAGE: http://www.ext2fsd.com 7 * UPDATE HISTORY: 8 */ 9 10/* INCLUDES *****************************************************************/ 11 12#include "ext2fs.h" 13 14/* GLOBALS ***************************************************************/ 15 16extern PEXT2_GLOBAL Ext2Global; 17 18/* DEFINITIONS *************************************************************/ 19 20#ifdef ALLOC_PRAGMA 21#pragma alloc_text(PAGE, Ext2Sleep) 22#endif 23 24ULONG 25Ext2Log2(ULONG Value) 26{ 27 ULONG Order = 0; 28 29 ASSERT(Value > 0); 30 31 while (Value) { 32 Order++; 33 Value >>= 1; 34 } 35 36 return (Order - 1); 37} 38 39LARGE_INTEGER 40Ext2NtTime (IN ULONG i_time) 41{ 42 LARGE_INTEGER SysTime; 43 44 SysTime.QuadPart = 0; 45 RtlSecondsSince1970ToTime(i_time, &SysTime); 46 47 return SysTime; 48} 49 50ULONG 51Ext2LinuxTime (IN LARGE_INTEGER SysTime) 52{ 53 ULONG Ext2Time = 0; 54 55 if (!RtlTimeToSecondsSince1970(&SysTime, &Ext2Time)) { 56 LARGE_INTEGER NtTime; 57 KeQuerySystemTime(&NtTime); 58 RtlTimeToSecondsSince1970(&NtTime, &Ext2Time); 59 } 60 61 return Ext2Time; 62} 63 64 65ULONG 66Ext2MbsToUnicode( 67 struct nls_table * PageTable, 68 IN OUT PUNICODE_STRING Unicode, 69 IN PANSI_STRING Mbs ) 70{ 71 ULONG Length = 0; 72 int i, mbc = 0; 73 WCHAR uc; 74 75 /* Count the length of the resulting Unicode. */ 76 for (i = 0; i < Mbs->Length; i += mbc) { 77 78 mbc = PageTable->char2uni( 79 (PUCHAR)&(Mbs->Buffer[i]), 80 Mbs->Length - i, 81 &uc 82 ); 83 84 if (mbc <= 0) { 85 86 /* invalid character. */ 87 if (mbc == 0 && Length > 0) { 88 break; 89 } 90 return 0; 91 } 92 93 Length += 2; 94 } 95 96 if (Unicode) { 97 if (Unicode->MaximumLength < Length) { 98 99 DbgBreak(); 100 return 0; 101 } 102 103 Unicode->Length = 0; 104 mbc = 0; 105 106 for (i = 0; i < Mbs->Length; i += mbc) { 107 108 mbc = PageTable->char2uni( 109 (PUCHAR)&(Mbs->Buffer[i]), 110 Mbs->Length - i, 111 &uc 112 ); 113 Unicode->Buffer[Unicode->Length/2] = uc; 114 Unicode->Length += 2; 115 } 116 } 117 118 return Length; 119} 120 121ULONG 122Ext2UnicodeToMbs ( 123 struct nls_table * PageTable, 124 IN OUT PANSI_STRING Mbs, 125 IN PUNICODE_STRING Unicode) 126{ 127 ULONG Length = 0; 128 UCHAR mbs[0x10]; 129 int i, mbc; 130 131 /* Count the length of the resulting mbc-8. */ 132 for (i = 0; i < (Unicode->Length / 2); i++) { 133 134 RtlZeroMemory(mbs, 0x10); 135 mbc = PageTable->uni2char( 136 Unicode->Buffer[i], 137 mbs, 138 0x10 139 ); 140 141 if (mbc <= 0) { 142 143 /* Invalid character. */ 144 return 0; 145 } 146 147 Length += mbc; 148 } 149 150 if (Mbs) { 151 152 if (Mbs->MaximumLength < Length) { 153 154 DbgBreak(); 155 return 0; 156 } 157 158 Mbs->Length = 0; 159 160 for (i = 0; i < (Unicode->Length / 2); i++) { 161 162 mbc = PageTable->uni2char( 163 Unicode->Buffer[i], 164 mbs, 165 0x10 166 ); 167 168 RtlCopyMemory( 169 (PUCHAR)&(Mbs->Buffer[Mbs->Length]), 170 &mbs[0], 171 mbc 172 ); 173 174 Mbs->Length += (USHORT)mbc; 175 } 176 } 177 178 return Length; 179} 180 181 182ULONG 183Ext2OEMToUnicodeSize( 184 IN PEXT2_VCB Vcb, 185 IN PANSI_STRING Oem 186) 187{ 188 ULONG Length = 0; 189 190 if (Vcb->Codepage.PageTable) { 191 Length = Ext2MbsToUnicode(Vcb->Codepage.PageTable, NULL, Oem); 192 if (Length > 0) { 193 goto errorout; 194 } 195 } 196 197 Length = RtlOemStringToCountedUnicodeSize(Oem); 198 199errorout: 200 201 return Length; 202} 203 204 205NTSTATUS 206Ext2OEMToUnicode( 207 IN PEXT2_VCB Vcb, 208 IN OUT PUNICODE_STRING Unicode, 209 IN POEM_STRING Oem 210) 211{ 212 NTSTATUS Status; 213 214 215 if (Vcb->Codepage.PageTable) { 216 Status = Ext2MbsToUnicode(Vcb->Codepage.PageTable, 217 Unicode, Oem); 218 219 if (Status >0 && Status == Unicode->Length) { 220 Status = STATUS_SUCCESS; 221 goto errorout; 222 } 223 } 224 225 Status = RtlOemStringToUnicodeString( 226 Unicode, Oem, FALSE ); 227 228 if (!NT_SUCCESS(Status)) { 229 DbgBreak(); 230 goto errorout; 231 } 232 233errorout: 234 235 return Status; 236} 237 238ULONG 239Ext2UnicodeToOEMSize( 240 IN PEXT2_VCB Vcb, 241 IN PUNICODE_STRING Unicode 242) 243{ 244 ULONG Length = 0; 245 246 if (Vcb->Codepage.PageTable) { 247 Length = Ext2UnicodeToMbs(Vcb->Codepage.PageTable, 248 NULL, Unicode); 249 if (Length > 0) { 250 return Length; 251 } 252 253 DbgBreak(); 254 } 255 256 return RtlxUnicodeStringToOemSize(Unicode); 257} 258 259 260NTSTATUS 261Ext2UnicodeToOEM ( 262 IN PEXT2_VCB Vcb, 263 IN OUT POEM_STRING Oem, 264 IN PUNICODE_STRING Unicode) 265{ 266 NTSTATUS Status; 267 268 if (Vcb->Codepage.PageTable) { 269 270 Status = Ext2UnicodeToMbs(Vcb->Codepage.PageTable, 271 Oem, Unicode); 272 if (Status > 0 && Status == Oem->Length) { 273 Status = STATUS_SUCCESS; 274 } else { 275 Status = STATUS_UNSUCCESSFUL; 276 DbgBreak(); 277 } 278 279 goto errorout; 280 } 281 282 Status = RtlUnicodeStringToOemString( 283 Oem, Unicode, FALSE ); 284 285 if (!NT_SUCCESS(Status)) 286 { 287 DbgBreak(); 288 goto errorout; 289 } 290 291errorout: 292 293 return Status; 294} 295 296VOID 297Ext2Sleep(ULONG ms) 298{ 299 LARGE_INTEGER Timeout; 300 Timeout.QuadPart = (LONGLONG)ms*1000*(-10); /* ms/1000 sec*/ 301 KeDelayExecutionThread(KernelMode, TRUE, &Timeout); 302} 303 304int Ext2LinuxError (NTSTATUS Status) 305{ 306 switch (Status) { 307 case STATUS_ACCESS_DENIED: 308 return (-EACCES); 309 310 case STATUS_ACCESS_VIOLATION: 311 return (-EFAULT); 312 313 case STATUS_BUFFER_TOO_SMALL: 314 return (-ETOOSMALL); 315 316 case STATUS_INVALID_PARAMETER: 317 return (-EINVAL); 318 319 case STATUS_NOT_IMPLEMENTED: 320 case STATUS_NOT_SUPPORTED: 321 return (-EOPNOTSUPP); 322 323 case STATUS_INVALID_ADDRESS: 324 case STATUS_INVALID_ADDRESS_COMPONENT: 325 return (-EADDRNOTAVAIL); 326 327 case STATUS_NO_SUCH_DEVICE: 328 case STATUS_NO_SUCH_FILE: 329 case STATUS_OBJECT_NAME_NOT_FOUND: 330 case STATUS_OBJECT_PATH_NOT_FOUND: 331 case STATUS_NETWORK_BUSY: 332 case STATUS_INVALID_NETWORK_RESPONSE: 333 case STATUS_UNEXPECTED_NETWORK_ERROR: 334 return (-ENETDOWN); 335 336 case STATUS_BAD_NETWORK_PATH: 337 case STATUS_NETWORK_UNREACHABLE: 338 case STATUS_PROTOCOL_UNREACHABLE: 339 return (-ENETUNREACH); 340 341 case STATUS_LOCAL_DISCONNECT: 342 case STATUS_TRANSACTION_ABORTED: 343 case STATUS_CONNECTION_ABORTED: 344 return (-ECONNABORTED); 345 346 case STATUS_REMOTE_DISCONNECT: 347 case STATUS_LINK_FAILED: 348 case STATUS_CONNECTION_DISCONNECTED: 349 case STATUS_CONNECTION_RESET: 350 case STATUS_PORT_UNREACHABLE: 351 return (-ECONNRESET); 352 353 case STATUS_INSUFFICIENT_RESOURCES: 354 return (-ENOMEM); 355 356 case STATUS_PAGEFILE_QUOTA: 357 case STATUS_NO_MEMORY: 358 case STATUS_CONFLICTING_ADDRESSES: 359 case STATUS_QUOTA_EXCEEDED: 360 case STATUS_TOO_MANY_PAGING_FILES: 361 case STATUS_WORKING_SET_QUOTA: 362 case STATUS_COMMITMENT_LIMIT: 363 case STATUS_TOO_MANY_ADDRESSES: 364 case STATUS_REMOTE_RESOURCES: 365 return (-ENOBUFS); 366 367 case STATUS_INVALID_CONNECTION: 368 return (-ENOTCONN); 369 370 case STATUS_PIPE_DISCONNECTED: 371 return (-ESHUTDOWN); 372 373 case STATUS_TIMEOUT: 374 case STATUS_IO_TIMEOUT: 375 case STATUS_LINK_TIMEOUT: 376 return (-ETIMEDOUT); 377 378 case STATUS_REMOTE_NOT_LISTENING: 379 case STATUS_CONNECTION_REFUSED: 380 return (-ECONNREFUSED); 381 382 case STATUS_HOST_UNREACHABLE: 383 return (-EHOSTUNREACH); 384 385 case STATUS_CANT_WAIT: 386 case STATUS_PENDING: 387 return (-EAGAIN); 388 389 case STATUS_DEVICE_NOT_READY: 390 return (-EIO); 391 392 case STATUS_CANCELLED: 393 case STATUS_REQUEST_ABORTED: 394 return (-EINTR); 395 396 case STATUS_BUFFER_OVERFLOW: 397 case STATUS_INVALID_BUFFER_SIZE: 398 return (-EMSGSIZE); 399 400 case STATUS_ADDRESS_ALREADY_EXISTS: 401 return (-EADDRINUSE); 402 } 403 404 if (NT_SUCCESS (Status)) 405 return 0; 406 407 return (-EINVAL); 408} 409 410NTSTATUS Ext2WinntError(int rc) 411{ 412 switch (rc) { 413 414 case 0: 415 return STATUS_SUCCESS; 416 417 case -EPERM: 418 case -EACCES: 419 return STATUS_ACCESS_DENIED; 420 421 case -ENOENT: 422 return STATUS_OBJECT_NAME_NOT_FOUND; 423 424 case -EFAULT: 425 return STATUS_ACCESS_VIOLATION; 426 427 case -ETOOSMALL: 428 return STATUS_BUFFER_TOO_SMALL; 429 430 case -EBADMSG: 431 case -EBADF: 432 case -EINVAL: 433 case -EFBIG: 434 return STATUS_INVALID_PARAMETER; 435 436 case -EBUSY: 437 return STATUS_DEVICE_BUSY; 438 439 case -ENOSYS: 440 return STATUS_NOT_IMPLEMENTED; 441 442 case -ENOSPC: 443 return STATUS_DISK_FULL; 444 445 case -EOPNOTSUPP: 446 return STATUS_NOT_SUPPORTED; 447 448 case -EDEADLK: 449 return STATUS_POSSIBLE_DEADLOCK; 450 451 case -EEXIST: 452 return STATUS_OBJECT_NAME_COLLISION; 453 454 case -EIO: 455 return STATUS_UNEXPECTED_IO_ERROR; 456 457 case -ENOTDIR: 458 return STATUS_NOT_A_DIRECTORY; 459 460 case -EISDIR: 461 return STATUS_FILE_IS_A_DIRECTORY; 462 463 case -ENOTEMPTY: 464 return STATUS_DIRECTORY_NOT_EMPTY; 465 466 case -ENODEV: 467 return STATUS_NO_SUCH_DEVICE; 468 469 case -ENXIO: 470 return STATUS_INVALID_ADDRESS; 471 472 case -EADDRNOTAVAIL: 473 return STATUS_INVALID_ADDRESS; 474 475 case -ENETDOWN: 476 return STATUS_UNEXPECTED_NETWORK_ERROR; 477 478 case -ENETUNREACH: 479 return STATUS_NETWORK_UNREACHABLE; 480 481 case -ECONNABORTED: 482 return STATUS_CONNECTION_ABORTED; 483 484 case -ECONNRESET: 485 return STATUS_CONNECTION_RESET; 486 487 case -ENOMEM: 488 return STATUS_INSUFFICIENT_RESOURCES; 489 490 case -ENOBUFS: 491 return STATUS_NO_MEMORY; 492 493 case -ENOTCONN: 494 return STATUS_INVALID_CONNECTION; 495 496 case -ESHUTDOWN: 497 return STATUS_CONNECTION_DISCONNECTED; 498 499 case -ETIMEDOUT: 500 return STATUS_TIMEOUT; 501 502 case -ECONNREFUSED: 503 return STATUS_CONNECTION_REFUSED; 504 505 case -EHOSTUNREACH: 506 return STATUS_HOST_UNREACHABLE; 507 508 case -EAGAIN: 509 return STATUS_CANT_WAIT; 510 511 case -EINTR: 512 return STATUS_CANCELLED; 513 514 case -EMSGSIZE: 515 return STATUS_INVALID_BUFFER_SIZE; 516 517 case -EADDRINUSE: 518 return STATUS_ADDRESS_ALREADY_EXISTS; 519 } 520 521 return STATUS_UNSUCCESSFUL; 522} 523 524BOOLEAN Ext2IsDot(PUNICODE_STRING name) 525{ 526 return (name->Length == 2 && name->Buffer[0] == L'.'); 527} 528 529BOOLEAN Ext2IsDotDot(PUNICODE_STRING name) 530{ 531 return (name->Length == 4 && name->Buffer[0] == L'.' && 532 name->Buffer[1] == L'.'); 533}