Changeset 2416 for trunk/src/kash/shfile.c
- Timestamp:
- Sep 14, 2010, 2:30:30 AM (15 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/kash/shfile.c
r2413 r2416 39 39 # define PIPE_BUF 512 40 40 # endif 41 # include <ntstatus.h> 42 # define WIN32_NO_STATUS 41 43 # include <Windows.h> 44 # if !defined(_WIN32_WINNT) 45 # define _WIN32_WINNT 0x0502 /* Windows Server 2003 */ 46 # endif 47 # include <winternl.h> //NTSTATUS 42 48 #else 43 49 # include <unistd.h> … … 86 92 87 93 # define MY_ObjectBasicInformation 0 88 typedef LONG (NTAPI * PFN_NtQueryObject)(HANDLE, int, void *, size_t, size_t *); 89 90 typedef struct MY_OBJECT_BASIC_INFORMATION94 # define MY_FileNamesInformation 12 95 96 typedef struct 91 97 { 92 98 ULONG Attributes; … … 103 109 } MY_OBJECT_BASIC_INFORMATION; 104 110 111 #if 0 112 typedef struct 113 { 114 union 115 { 116 LONG Status; 117 PVOID Pointer; 118 }; 119 ULONG_PTR Information; 120 } MY_IO_STATUS_BLOCK; 121 #else 122 typedef IO_STATUS_BLOCK MY_IO_STATUS_BLOCK; 123 #endif 124 typedef MY_IO_STATUS_BLOCK *PMY_IO_STATUS_BLOCK; 125 126 typedef struct 127 { 128 ULONG NextEntryOffset; 129 ULONG FileIndex; 130 ULONG FileNameLength; 131 WCHAR FileName[1]; 132 } MY_FILE_NAMES_INFORMATION, *PMY_FILE_NAMES_INFORMATION; 133 134 typedef NTSTATUS (NTAPI * PFN_NtQueryObject)(HANDLE, int, void *, size_t, size_t *); 135 typedef NTSTATUS (NTAPI * PFN_NtQueryDirectoryFile)(HANDLE, HANDLE, void *, void *, PMY_IO_STATUS_BLOCK, void *, 136 ULONG, int, int, PUNICODE_STRING, int); 137 typedef NTSTATUS (NTAPI * PFN_RtlUnicodeStringToAnsiString)(PANSI_STRING, PCUNICODE_STRING, int); 138 139 140 #endif /* K_OS_WINDOWS */ 141 142 143 /******************************************************************************* 144 * Global Variables * 145 *******************************************************************************/ 146 #if K_OS == K_OS_WINDOWS 147 static int g_shfile_globals_initialized = 0; 148 static PFN_NtQueryObject g_pfnNtQueryObject = NULL; 149 static PFN_NtQueryDirectoryFile g_pfnNtQueryDirectoryFile = NULL; 150 static PFN_RtlUnicodeStringToAnsiString g_pfnRtlUnicodeStringToAnsiString = NULL; 105 151 #endif /* K_OS_WINDOWS */ 106 152 … … 387 433 } 388 434 435 /** 436 * Converts an NT status code to errno, 437 * assigning it to errno. 438 * 439 * @returns -1 440 * @param rcNt The NT status code. 441 */ 442 static int shfile_nt2errno(NTSTATUS rcNt) 443 { 444 switch (rcNt) 445 { 446 default: errno = EINVAL; break; 447 } 448 return -1; 449 } 450 389 451 DWORD shfile_query_handle_access_mask(HANDLE h, PACCESS_MASK pMask) 390 452 { 391 static PFN_NtQueryObject s_pfnNtQueryObject = NULL;392 453 MY_OBJECT_BASIC_INFORMATION BasicInfo; 393 LONG Status; 394 395 if (!s_pfnNtQueryObject) 396 { 397 s_pfnNtQueryObject = (PFN_NtQueryObject)GetProcAddress(GetModuleHandle("NTDLL"), "NtQueryObject"); 398 if (!s_pfnNtQueryObject) 399 return ERROR_NOT_SUPPORTED; 400 } 401 402 Status = s_pfnNtQueryObject(h, MY_ObjectBasicInformation, &BasicInfo, sizeof(BasicInfo), NULL); 403 if (Status >= 0) 454 NTSTATUS rcNt; 455 456 if (!g_pfnNtQueryObject) 457 return ERROR_NOT_SUPPORTED; 458 459 rcNt = g_pfnNtQueryObject(h, MY_ObjectBasicInformation, &BasicInfo, sizeof(BasicInfo), NULL); 460 if (rcNt >= 0) 404 461 { 405 462 *pMask = BasicInfo.GrantedAccess; 406 463 return NO_ERROR; 407 464 } 408 if ( Status!= STATUS_INVALID_HANDLE)465 if (rcNt != STATUS_INVALID_HANDLE) 409 466 return ERROR_GEN_FAILURE; 410 467 return ERROR_INVALID_HANDLE; … … 414 471 415 472 #endif /* SHFILE_IN_USE */ 473 474 /** 475 * Initializes the global variables in this file. 476 */ 477 static void shfile_init_globals(void) 478 { 479 #if K_OS == K_OS_WINDOWS 480 if (!g_shfile_globals_initialized) 481 { 482 HMODULE hNtDll = GetModuleHandle("NTDLL"); 483 g_pfnNtQueryObject = (PFN_NtQueryObject) GetProcAddress(hNtDll, "NtQueryObject"); 484 g_pfnNtQueryDirectoryFile = (PFN_NtQueryDirectoryFile)GetProcAddress(hNtDll, "NtQueryDirectoryFile"); 485 g_pfnRtlUnicodeStringToAnsiString = (PFN_RtlUnicodeStringToAnsiString)GetProcAddress(hNtDll, "RtlUnicodeStringToAnsiString"); 486 if ( !g_pfnRtlUnicodeStringToAnsiString 487 || !g_pfnNtQueryDirectoryFile) 488 { 489 /* fatal error */ 490 } 491 g_shfile_globals_initialized = 1; 492 } 493 #endif 494 } 416 495 417 496 /** … … 426 505 { 427 506 int rc; 507 508 shfile_init_globals(); 428 509 429 510 pfdtab->cwd = NULL; … … 1417 1498 1418 1499 1500 1419 1501 shdir *shfile_opendir(shfdtab *pfdtab, const char *dir) 1420 1502 { 1421 1503 #ifdef SHFILE_IN_USE 1422 errno = ENOSYS; 1423 return NULL; 1504 shdir *pdir = NULL; 1505 1506 if (g_pfnNtQueryDirectoryFile) 1507 { 1508 char abspath[SHFILE_MAX_PATH]; 1509 if (shfile_make_path(pfdtab, dir, &abspath[0]) == 0) 1510 { 1511 HANDLE hFile; 1512 SECURITY_ATTRIBUTES SecurityAttributes; 1513 1514 SecurityAttributes.nLength = sizeof(SecurityAttributes); 1515 SecurityAttributes.lpSecurityDescriptor = NULL; 1516 SecurityAttributes.bInheritHandle = FALSE; 1517 1518 hFile = CreateFileA(abspath, 1519 GENERIC_READ, 1520 FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, 1521 &SecurityAttributes, 1522 OPEN_ALWAYS, 1523 FILE_ATTRIBUTE_DIRECTORY | FILE_FLAG_BACKUP_SEMANTICS, 1524 NULL /* hTemplateFile */); 1525 if (hFile != INVALID_HANDLE_VALUE) 1526 { 1527 pdir = (shdir *)sh_malloc(shthread_get_shell(), sizeof(*pdir)); 1528 if (pdir) 1529 { 1530 pdir->pfdtab = pfdtab; 1531 pdir->native = hFile; 1532 pdir->off = ~(size_t)0; 1533 } 1534 else 1535 CloseHandle(hFile); 1536 } 1537 else 1538 shfile_dos2errno(GetLastError()); 1539 } 1540 } 1541 else 1542 errno = ENOSYS; 1543 return pdir; 1424 1544 #else 1425 1545 return (shdir *)opendir(dir); … … 1430 1550 { 1431 1551 #ifdef SHFILE_IN_USE 1432 errno = ENOSYS; 1552 if (pdir) 1553 { 1554 NTSTATUS rcNt; 1555 1556 if ( pdir->off == ~(size_t)0 1557 || pdir->off + sizeof(MY_FILE_NAMES_INFORMATION) >= pdir->cb) 1558 { 1559 MY_IO_STATUS_BLOCK Ios; 1560 1561 memset(&Ios, 0, sizeof(Ios)); 1562 rcNt = g_pfnNtQueryDirectoryFile(pdir->native, 1563 NULL /*Event*/, 1564 NULL /*ApcRoutine*/, 1565 NULL /*ApcContext*/, 1566 &Ios, 1567 &pdir->buf[0], 1568 sizeof(pdir->buf), 1569 MY_FileNamesInformation, 1570 FALSE /*ReturnSingleEntry*/, 1571 NULL /*FileName*/, 1572 pdir->off == ~(size_t)0 /*RestartScan*/); 1573 if (rcNt >= 0 && rcNt != STATUS_PENDING) 1574 { 1575 pdir->cb = Ios.Information; 1576 pdir->off = 0; 1577 } 1578 else if (rcNt == STATUS_NO_MORE_FILES) 1579 errno = 0; /* wrong? */ 1580 else 1581 shfile_nt2errno(rcNt); 1582 } 1583 1584 if ( pdir->off != ~(size_t)0 1585 && pdir->off + sizeof(MY_FILE_NAMES_INFORMATION) <= pdir->cb) 1586 { 1587 PMY_FILE_NAMES_INFORMATION pcur = (PMY_FILE_NAMES_INFORMATION)&pdir->buf[pdir->off]; 1588 ANSI_STRING astr; 1589 UNICODE_STRING ustr; 1590 1591 astr.Length = astr.MaximumLength = sizeof(pdir->ent.name); 1592 astr.Buffer = &pdir->ent.name[0]; 1593 1594 ustr.Length = ustr.MaximumLength = pcur->FileNameLength < ~(USHORT)0 ? (USHORT)pcur->FileNameLength : ~(USHORT)0; 1595 ustr.Buffer = &pcur->FileName[0]; 1596 1597 rcNt = g_pfnRtlUnicodeStringToAnsiString(&astr, &ustr, 0/*AllocateDestinationString*/); 1598 if (rcNt < 0) 1599 sprintf(pdir->ent.name, "conversion-failed-%08x-rcNt=%08x-len=%u", 1600 pcur->FileIndex, rcNt, pcur->FileNameLength); 1601 if (pcur->NextEntryOffset) 1602 pdir->off += pcur->NextEntryOffset; 1603 else 1604 pdir->off = pdir->cb; 1605 return &pdir->ent; 1606 } 1607 } 1608 else 1609 errno = EINVAL; 1433 1610 return NULL; 1434 1611 #else … … 1441 1618 { 1442 1619 #ifdef SHFILE_IN_USE 1443 errno = ENOSYS; 1620 if (pdir) 1621 { 1622 CloseHandle(pdir->native); 1623 pdir->pfdtab = NULL; 1624 pdir->native = INVALID_HANDLE_VALUE; 1625 sh_free(shthread_get_shell(), pdir); 1626 } 1627 else 1628 errno = EINVAL; 1444 1629 #else 1445 1630 closedir((DIR *)pdir);
Note:
See TracChangeset
for help on using the changeset viewer.