NTSTATUS FindHardDiskForPartition(PUNICODE_STRING pNameUnicodeString, PWCHAR pOutRequest, ULONG OutRequestSize, ULONG *pRetSize) { NTSTATUS ntRetStatus = STATUS_NOT_FOUND; NTSTATUS ntStatus; BYTE cou; OBJECT_ATTRIBUTES ObjAttr; HANDLE hDirectoryObject; BOOLEAN First; POBJECT_NAMETYPE_INFO p; HANDLE DrvHandle; PDRIVER_OBJECT pDrv; UNICODE_STRING Name; PWCHAR DrvName; PWCHAR DriverStr=L"Partition"; WCHAR Dir[128]; ULONG RegionSize; PMY_QUERY_DIRECTORY_STRUCT qds; qds = NULL; RegionSize = sizeof(MY_QUERY_DIRECTORY_STRUCT); if(!NT_SUCCESS(ntStatus = ZwAllocateVirtualMemory((HANDLE)-1, (PVOID*) &qds, 0, &RegionSize, // ^ - Whistler beta 2 doesn't work with 8 MEM_COMMIT,PAGE_READWRITE))) { DbPrint(DC_LLDISKIO, DL_ERROR,("ZwAllocateVirtualMemory fail. Status=%x\n", ntStatus)); } else { PWCHAR pdrvid; for(cou = 0; cou <= 9 && ntRetStatus != STATUS_SUCCESS; cou++) { wcscpy(Dir, L"\\Device\\Harddisk0"); pdrvid = &Dir[wcslen(Dir) - 1]; *(BYTE*)pdrvid += cou; RtlInitUnicodeString(&Name, Dir); InitializeObjectAttributes(&ObjAttr, &Name, OBJ_CASE_INSENSITIVE, NULL, NULL); ntStatus=ZwOpenDirectoryObject(&hDirectoryObject, DIRECTORY_QUERY, &ObjAttr); if(NT_SUCCESS(ntStatus)) { First=TRUE; DrvName=Dir+wcslen(Dir); *DrvName++='\\'; while(NtQueryDirectoryObject(hDirectoryObject, &qds->Buffer, QUERY_DIRECTORY_BUFF_SIZE, TRUE, First, &qds->Index, &qds->Retlen) >= 0 && ntRetStatus != STATUS_SUCCESS) { p=(POBJECT_NAMETYPE_INFO)&qds->Buffer; First=FALSE; *DrvName=0; if(wcsncmp(p->ObjectName.Buffer, DriverStr, 9)) continue; else { HANDLE hLink; InitializeObjectAttributes(&ObjAttr, &p->ObjectName, OBJ_CASE_INSENSITIVE, hDirectoryObject, NULL); ntStatus = ZwOpenSymbolicLinkObject(&hLink, SYMBOLIC_LINK_QUERY, &ObjAttr); if(NT_SUCCESS(ntStatus)) { WCHAR targetNameBuffer[260]; UNICODE_STRING targetNameUnicodeString; RtlZeroMemory(targetNameBuffer, sizeof(targetNameBuffer)); targetNameUnicodeString.Buffer = targetNameBuffer; targetNameUnicodeString.MaximumLength = sizeof(targetNameBuffer); ntStatus = ZwQuerySymbolicLinkObject(hLink, &targetNameUnicodeString, NULL); if(NT_SUCCESS(ntStatus) && (RtlCompareUnicodeString(&targetNameUnicodeString, pNameUnicodeString, FALSE) == 0)) { int number = GetHarddiskId(Dir); if (number != -1) { int cou2; int drvstrlen; char drstr[32]; sprintf(drstr, "%d", number); drvstrlen = strlen(drstr); wcscpy(pOutRequest, Dir); wcscat(pOutRequest, L"DR"); pdrvid = &pOutRequest[wcslen(pOutRequest) - 1] + 1; for (cou2 = 0; cou2 < drvstrlen; cou2++) { *pdrvid = (WCHAR) (drstr[cou2]); pdrvid++; } *pdrvid = 0; DbPrint(DC_LLDISKIO, DL_INFO, ("FindHardDiskForPartition found %S\n", pOutRequest)); *pRetSize = (wcslen(pOutRequest) + 1 ) * 2; ntRetStatus = STATUS_SUCCESS; } } ZwClose(hLink); } } } ZwClose(hDirectoryObject); } } } RegionSize = 0; _pfZwFreeVirtualMemory((HANDLE)-1,(PVOID*) &qds,&RegionSize,MEM_RELEASE); return ntRetStatus; }
/** * Fetches more data from the file system. * * @returns IPRT status code * @param pThis The directory instance data. */ static int rtDirNtFetchMore(PRTDIR pThis) { Assert(!pThis->fDataUnread); /* * Allocate the buffer the first time around. * We do this in lazy fashion as some users of RTDirOpen will not actually * list any files, just open it for various reasons. */ bool fFirst = false; if (!pThis->pabBuffer) { fFirst = false; pThis->cbBufferAlloc = _256K; pThis->pabBuffer = (uint8_t *)RTMemAlloc(pThis->cbBufferAlloc); if (!pThis->pabBuffer) { do { pThis->cbBufferAlloc /= 4; pThis->pabBuffer = (uint8_t *)RTMemAlloc(pThis->cbBufferAlloc); } while (pThis->pabBuffer == NULL && pThis->cbBufferAlloc > _4K); if (!pThis->pabBuffer) return VERR_NO_MEMORY; } } /* * Read more. */ NTSTATUS rcNt; IO_STATUS_BLOCK Ios = MY_IO_STATUS_BLOCK_INITIALIZER; if (pThis->enmInfoClass != (FILE_INFORMATION_CLASS)0) { #ifdef IPRT_WITH_NT_PATH_PASSTHRU if (pThis->enmInfoClass == FileMaximumInformation) { Ios.Information = 0; Ios.Status = rcNt = NtQueryDirectoryObject(pThis->hDir, pThis->pabBuffer, pThis->cbBufferAlloc, RTDIR_NT_SINGLE_RECORD /*ReturnSingleEntry */, FALSE /*RestartScan*/, &pThis->uObjDirCtx, (PULONG)&Ios.Information); } else #endif rcNt = NtQueryDirectoryFile(pThis->hDir, NULL /* Event */, NULL /* ApcRoutine */, NULL /* ApcContext */, &Ios, pThis->pabBuffer, pThis->cbBufferAlloc, pThis->enmInfoClass, RTDIR_NT_SINGLE_RECORD /*ReturnSingleEntry */, pThis->pNtFilterStr, FALSE /*RestartScan */); } else { /* * The first time around we have figure which info class we can use. * We prefer one which gives us file IDs, but we'll settle for less. */ pThis->enmInfoClass = FileIdBothDirectoryInformation; rcNt = NtQueryDirectoryFile(pThis->hDir, NULL /* Event */, NULL /* ApcRoutine */, NULL /* ApcContext */, &Ios, pThis->pabBuffer, pThis->cbBufferAlloc, pThis->enmInfoClass, RTDIR_NT_SINGLE_RECORD /*ReturnSingleEntry */, pThis->pNtFilterStr, FALSE /*RestartScan */); if (!NT_SUCCESS(rcNt)) { pThis->enmInfoClass = FileBothDirectoryInformation; rcNt = NtQueryDirectoryFile(pThis->hDir, NULL /* Event */, NULL /* ApcRoutine */, NULL /* ApcContext */, &Ios, pThis->pabBuffer, pThis->cbBufferAlloc, pThis->enmInfoClass, RTDIR_NT_SINGLE_RECORD /*ReturnSingleEntry */, pThis->pNtFilterStr, FALSE /*RestartScan */); } } if (!NT_SUCCESS(rcNt)) { if (rcNt == STATUS_NO_MORE_FILES || rcNt == STATUS_NO_MORE_ENTRIES) return VERR_NO_MORE_FILES; return RTErrConvertFromNtStatus(rcNt); } Assert(Ios.Information > sizeof(*pThis->uCurData.pBoth)); /* * Set up the data members. */ pThis->uCurData.u = (uintptr_t)pThis->pabBuffer; pThis->cbBuffer = Ios.Information; int rc = rtDirNtCheckRecord(pThis); pThis->fDataUnread = RT_SUCCESS(rc); return rc; }
int GetHarddiskId(PWCHAR pwchDir) { NTSTATUS ntStatus; int nRet = -1; OBJECT_ATTRIBUTES ObjAttr; HANDLE hDirectoryObject; UNICODE_STRING Name; WCHAR DriverStr[32]; PWCHAR pdrvid; int len ; PMY_QUERY_DIRECTORY_STRUCT qds; POBJECT_NAMETYPE_INFO p; ULONG RegionSize; int cou; qds = NULL; RegionSize = sizeof(MY_QUERY_DIRECTORY_STRUCT); if(!NT_SUCCESS(ntStatus = ZwAllocateVirtualMemory((HANDLE)-1, (PVOID*) &qds, 0, &RegionSize, MEM_COMMIT,PAGE_READWRITE))) { return nRet; } wcscpy(DriverStr, L"DR0"); len = wcslen(DriverStr); pdrvid = &DriverStr[len - 1]; RtlInitUnicodeString(&Name, pwchDir); Name.Length -= sizeof(WCHAR); InitializeObjectAttributes(&ObjAttr, &Name, OBJ_CASE_INSENSITIVE, NULL, NULL); ntStatus = ZwOpenDirectoryObject(&hDirectoryObject, DIRECTORY_QUERY, &ObjAttr); if(NT_SUCCESS(ntStatus)) { BOOLEAN First = TRUE; while(NtQueryDirectoryObject(hDirectoryObject, &qds->Buffer, QUERY_DIRECTORY_BUFF_SIZE, TRUE, First, &qds->Index, &qds->Retlen) >= 0 && nRet == -1) { PWCHAR obj_name; int tmp_len; p = (POBJECT_NAMETYPE_INFO)&qds->Buffer; First = FALSE; obj_name = p->ObjectName.Buffer; tmp_len = p->ObjectName.Length / sizeof(WCHAR); if (tmp_len >= 3) { // TAK POLUCHILOS! :) if (obj_name[0] == L'D' && obj_name[1] == L'R') { BOOLEAN bisdigit = TRUE; int cou2; int ntmp = 0; for (cou2 = 2; cou2 < tmp_len; cou2++) { if (obj_name[cou2] < L'0' || obj_name[cou2] > L'9') { bisdigit = FALSE; break; } ntmp = ntmp * 10 + (obj_name[cou2] - L'0'); } if (bisdigit) nRet = ntmp; } } } ZwClose(hDirectoryObject); } _pfZwFreeVirtualMemory((HANDLE)-1,(PVOID*) &qds, &RegionSize,MEM_RELEASE); return nRet; }
VOID DumpObjectDirs( IN PCH DirName, IN ULONG Level ) { OBJECT_ATTRIBUTES ObjectAttributes; STRING Name; HANDLE Handle; ULONG Context, Length; NTSTATUS Status; BOOLEAN RestartScan; POBJECT_DIRECTORY_INFORMATION DirInfo; CHAR DirInfoBuffer[ 256 ]; CHAR SubDirName[ 128 ]; STRING LinkName; STRING LinkTarget; HANDLE LinkHandle; RtlInitString( &Name, DirName ); InitializeObjectAttributes( &ObjectAttributes, &Name, OBJ_OPENIF | OBJ_CASE_INSENSITIVE, NULL, NULL ); NtCreateDirectoryObject( &Handle, DIRECTORY_ALL_ACCESS, &ObjectAttributes ); DirInfo = (POBJECT_DIRECTORY_INFORMATION)&DirInfoBuffer; RestartScan = TRUE; while (TRUE) { Status = NtQueryDirectoryObject( Handle, (PVOID)DirInfo, sizeof( DirInfoBuffer ), TRUE, RestartScan, &Context, &Length ); if (!NT_SUCCESS( Status )) { break; } DbgPrint( "%s%s%Z - %Z", DirName, Level ? "\\" : "", &DirInfo->Name, &DirInfo->TypeName ); if (RtlEqualString( &DirInfo->TypeName, &DirTypeName, TRUE )) { DbgPrint( "\n" ); strcpy( SubDirName, DirName ); if (Level) { strcat( SubDirName, "\\" ); } strcat( SubDirName, DirInfo->Name.Buffer ); DumpObjectDirs( SubDirName, Level+1 ); } else if (RtlEqualString( &DirInfo->TypeName, &LinkTypeName, TRUE )) { strcpy( SubDirName, DirName ); if (Level) { strcat( SubDirName, "\\" ); } strcat( SubDirName, DirInfo->Name.Buffer ); RtlInitString( &LinkName, SubDirName ); InitializeObjectAttributes( &ObjectAttributes, &LinkName, 0, NULL, NULL ); Status = NtOpenSymbolicLinkObject( &LinkHandle, SYMBOLIC_LINK_ALL_ACCESS, &ObjectAttributes ); if (!NT_SUCCESS( Status )) { DbgPrint( " - unable to open symbolic link (%X)\n", Status ); } else { LinkTarget.MaximumLength = sizeof( SubDirName ); LinkTarget.Length = 0; LinkTarget.Buffer = SubDirName; Status = NtQuerySymbolicLinkObject( LinkHandle, &LinkTarget ); if (!NT_SUCCESS( Status )) { DbgPrint( " - unable to query symbolic link target (%X)\n", Status ); } else { DbgPrint( " => %Z\n", &LinkTarget ); } NtClose( LinkHandle ); } } else { DbgPrint( "\n" ); } RestartScan = FALSE; } NtClose( Handle ); }
/* * @implemented */ DWORD WINAPI QueryDosDeviceW( LPCWSTR lpDeviceName, LPWSTR lpTargetPath, DWORD ucchMax ) { POBJECT_DIRECTORY_INFORMATION DirInfo; OBJECT_ATTRIBUTES ObjectAttributes; UNICODE_STRING UnicodeString; HANDLE DirectoryHandle; HANDLE DeviceHandle; ULONG ReturnLength; ULONG NameLength; ULONG Length; ULONG Context; BOOLEAN RestartScan; NTSTATUS Status; UCHAR Buffer[512]; PWSTR Ptr; /* Open the '\??' directory */ RtlInitUnicodeString (&UnicodeString, L"\\??"); InitializeObjectAttributes (&ObjectAttributes, &UnicodeString, OBJ_CASE_INSENSITIVE, NULL, NULL); Status = NtOpenDirectoryObject (&DirectoryHandle, DIRECTORY_QUERY, &ObjectAttributes); if (!NT_SUCCESS (Status)) { WARN ("NtOpenDirectoryObject() failed (Status %lx)\n", Status); BaseSetLastNTError (Status); return 0; } Length = 0; if (lpDeviceName != NULL) { /* Open the lpDeviceName link object */ RtlInitUnicodeString (&UnicodeString, (PWSTR)lpDeviceName); InitializeObjectAttributes (&ObjectAttributes, &UnicodeString, OBJ_CASE_INSENSITIVE, DirectoryHandle, NULL); Status = NtOpenSymbolicLinkObject (&DeviceHandle, SYMBOLIC_LINK_QUERY, &ObjectAttributes); if (!NT_SUCCESS (Status)) { WARN ("NtOpenSymbolicLinkObject() failed (Status %lx)\n", Status); NtClose (DirectoryHandle); BaseSetLastNTError (Status); return 0; } /* Query link target */ UnicodeString.Length = 0; UnicodeString.MaximumLength = (USHORT)ucchMax * sizeof(WCHAR); UnicodeString.Buffer = lpTargetPath; ReturnLength = 0; Status = NtQuerySymbolicLinkObject (DeviceHandle, &UnicodeString, &ReturnLength); NtClose (DeviceHandle); NtClose (DirectoryHandle); if (!NT_SUCCESS (Status)) { WARN ("NtQuerySymbolicLinkObject() failed (Status %lx)\n", Status); BaseSetLastNTError (Status); return 0; } TRACE ("ReturnLength: %lu\n", ReturnLength); TRACE ("TargetLength: %hu\n", UnicodeString.Length); TRACE ("Target: '%wZ'\n", &UnicodeString); Length = UnicodeString.Length / sizeof(WCHAR); if (Length < ucchMax) { /* Append null-charcter */ lpTargetPath[Length] = UNICODE_NULL; Length++; } else { TRACE ("Buffer is too small\n"); BaseSetLastNTError (STATUS_BUFFER_TOO_SMALL); return 0; } } else { RestartScan = TRUE; Context = 0; Ptr = lpTargetPath; DirInfo = (POBJECT_DIRECTORY_INFORMATION)Buffer; while (TRUE) { Status = NtQueryDirectoryObject (DirectoryHandle, Buffer, sizeof (Buffer), TRUE, RestartScan, &Context, &ReturnLength); if (!NT_SUCCESS(Status)) { if (Status == STATUS_NO_MORE_ENTRIES) { /* Terminate the buffer */ *Ptr = UNICODE_NULL; Length++; Status = STATUS_SUCCESS; } else { Length = 0; } BaseSetLastNTError (Status); break; } if (!wcscmp (DirInfo->TypeName.Buffer, L"SymbolicLink")) { TRACE ("Name: '%wZ'\n", &DirInfo->Name); NameLength = DirInfo->Name.Length / sizeof(WCHAR); if (Length + NameLength + 1 >= ucchMax) { Length = 0; BaseSetLastNTError (STATUS_BUFFER_TOO_SMALL); break; } memcpy (Ptr, DirInfo->Name.Buffer, DirInfo->Name.Length); Ptr += NameLength; Length += NameLength; *Ptr = UNICODE_NULL; Ptr++; Length++; } RestartScan = FALSE; } NtClose (DirectoryHandle); } return Length; }
/** * Deal with getting info about something that could be in a directory object. * * @returns IPRT status code * @param pObjAttr The NT object attribute. * @param pObjInfo Where to return the info. * @param enmAddAttr Which extra attributes to get (/fake). * @param fFlags The flags. * @param pvBuf Query buffer space. * @param cbBuf Size of the buffer. ASSUMES lots of space. * @param rcNtCaller The status code that got us here. */ static int rtPathNtQueryInfoInDirectoryObject(OBJECT_ATTRIBUTES *pObjAttr, PRTFSOBJINFO pObjInfo, RTFSOBJATTRADD enmAddAttr, uint32_t fFlags, void *pvBuf, size_t cbBuf, NTSTATUS rcNtCaller) { RT_NOREF(fFlags); /* * Special case: Root dir. */ if ( pObjAttr->RootDirectory == NULL && pObjAttr->ObjectName->Length == sizeof(RTUTF16) && pObjAttr->ObjectName->Buffer[0] == '\\') { pObjInfo->cbObject = 0; pObjInfo->cbAllocated = 0; RTTimeSpecSetNtTime(&pObjInfo->BirthTime, 0); RTTimeSpecSetNtTime(&pObjInfo->AccessTime, 0); RTTimeSpecSetNtTime(&pObjInfo->ModificationTime, 0); RTTimeSpecSetNtTime(&pObjInfo->ChangeTime, 0); pObjInfo->Attr.fMode = RTFS_DOS_DIRECTORY | RTFS_TYPE_DIRECTORY | 0777; return rtPathNtQueryInfoFillInDummyData(VINF_SUCCESS, pObjInfo, enmAddAttr); } /* * We must open and scan the parent directory object. */ UNICODE_STRING NtDirName; UNICODE_STRING NtDirEntry; ntPathNtSplitName(pObjAttr->ObjectName, &NtDirName, &NtDirEntry, true /*fNoParentDirSlash*/); while ( NtDirEntry.Length > sizeof(RTUTF16) && NtDirEntry.Buffer[NtDirEntry.Length / sizeof(RTUTF16) - 1] == '\\') NtDirEntry.Length -= sizeof(RTUTF16); pObjAttr->ObjectName = &NtDirName; HANDLE hDir = RTNT_INVALID_HANDLE_VALUE; NTSTATUS rcNt = NtOpenDirectoryObject(&hDir, DIRECTORY_QUERY | DIRECTORY_TRAVERSE, pObjAttr); if (NT_SUCCESS(rcNt)) { ULONG uObjDirCtx = 0; for (;;) { ULONG cbReturned = 0; rcNt = NtQueryDirectoryObject(hDir, pvBuf, (ULONG)cbBuf, FALSE /*ReturnSingleEntry */, FALSE /*RestartScan*/, &uObjDirCtx, &cbReturned); if (!NT_SUCCESS(rcNt)) break; for (POBJECT_DIRECTORY_INFORMATION pObjDir = (POBJECT_DIRECTORY_INFORMATION)pvBuf; pObjDir->Name.Length != 0; pObjDir++) { if ( pObjDir->Name.Length == NtDirEntry.Length && memcmp(pObjDir->Name.Buffer, NtDirEntry.Buffer, NtDirEntry.Length) == 0) { /* * Find it. Fill in the info we've got and return (see similar code in direnum-r3-nt.cpp). */ NtClose(hDir); pObjInfo->cbObject = 0; pObjInfo->cbAllocated = 0; RTTimeSpecSetNtTime(&pObjInfo->BirthTime, 0); RTTimeSpecSetNtTime(&pObjInfo->AccessTime, 0); RTTimeSpecSetNtTime(&pObjInfo->ModificationTime, 0); RTTimeSpecSetNtTime(&pObjInfo->ChangeTime, 0); if (ARE_UNICODE_STRINGS_EQUAL(&pObjDir->TypeName, L"Directory")) pObjInfo->Attr.fMode = RTFS_DOS_DIRECTORY | RTFS_TYPE_DIRECTORY | 0777; else if (ARE_UNICODE_STRINGS_EQUAL(&pObjDir->TypeName, L"SymbolicLink")) pObjInfo->Attr.fMode = RTFS_DOS_NT_REPARSE_POINT | RTFS_TYPE_SYMLINK | 0777; else if (ARE_UNICODE_STRINGS_EQUAL(&pObjDir->TypeName, L"Device")) pObjInfo->Attr.fMode = RTFS_DOS_NT_DEVICE | RTFS_TYPE_DEV_CHAR | 0666; else pObjInfo->Attr.fMode = RTFS_DOS_NT_NORMAL | RTFS_TYPE_FILE | 0666; pObjInfo->Attr.enmAdditional = enmAddAttr; return rtPathNtQueryInfoFillInDummyData(VINF_SUCCESS, pObjInfo, enmAddAttr); } } } NtClose(hDir); if (rcNt == STATUS_NO_MORE_FILES || rcNt == STATUS_NO_MORE_ENTRIES || rcNt == STATUS_NO_SUCH_FILE) return VERR_FILE_NOT_FOUND; } else return RTErrConvertFromNtStatus(rcNtCaller); return RTErrConvertFromNtStatus(rcNt); }
static DWORD ScmGetDriverStatus(PSERVICE lpService, LPSERVICE_STATUS lpServiceStatus) { OBJECT_ATTRIBUTES ObjectAttributes; UNICODE_STRING DirName; HANDLE DirHandle; NTSTATUS Status = STATUS_SUCCESS; POBJECT_DIRECTORY_INFORMATION DirInfo; ULONG BufferLength; ULONG DataLength; ULONG Index; DWORD dwError = ERROR_SUCCESS; BOOLEAN bFound = FALSE; DWORD dwPreviousState; DPRINT1("ScmGetDriverStatus() called\n"); /* Zero output buffer if any */ if (lpServiceStatus != NULL) { memset(lpServiceStatus, 0, sizeof(SERVICE_STATUS)); } /* Select the appropriate object directory based on driver type */ if (lpService->Status.dwServiceType == SERVICE_KERNEL_DRIVER) { RtlInitUnicodeString(&DirName, L"\\Driver"); } else // if (lpService->Status.dwServiceType == SERVICE_FILE_SYSTEM_DRIVER) { ASSERT(lpService->Status.dwServiceType == SERVICE_FILE_SYSTEM_DRIVER); RtlInitUnicodeString(&DirName, L"\\FileSystem"); } InitializeObjectAttributes(&ObjectAttributes, &DirName, 0, NULL, NULL); /* Open the object directory where loaded drivers are */ Status = NtOpenDirectoryObject(&DirHandle, DIRECTORY_QUERY | DIRECTORY_TRAVERSE, &ObjectAttributes); if (!NT_SUCCESS(Status)) { DPRINT1("NtOpenDirectoryObject() failed!\n"); return RtlNtStatusToDosError(Status); } /* Allocate a buffer big enough for querying the object */ BufferLength = sizeof(OBJECT_DIRECTORY_INFORMATION) + 2 * MAX_PATH * sizeof(WCHAR); DirInfo = (OBJECT_DIRECTORY_INFORMATION*) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, BufferLength); /* Now, start browsing entry by entry */ Index = 0; while (TRUE) { Status = NtQueryDirectoryObject(DirHandle, DirInfo, BufferLength, TRUE, FALSE, &Index, &DataLength); /* End of enumeration, the driver was not found */ if (Status == STATUS_NO_MORE_ENTRIES) { DPRINT("No more services\n"); break; } /* Other error, fail */ if (!NT_SUCCESS(Status)) break; DPRINT("Comparing: '%S' '%wZ'\n", lpService->lpServiceName, &DirInfo->Name); /* Compare names to check whether it matches our driver */ if (_wcsicmp(lpService->lpServiceName, DirInfo->Name.Buffer) == 0) { /* That's our driver, bail out! */ DPRINT1("Found: '%S' '%wZ'\n", lpService->lpServiceName, &DirInfo->Name); bFound = TRUE; break; } } /* Release resources we don't need */ HeapFree(GetProcessHeap(), 0, DirInfo); NtClose(DirHandle); /* Only quit if there's a failure * Not having found the driver is legit! * It means the driver was registered as a service, but not loaded * We have not to fail in that situation, but to return proper status */ if (!NT_SUCCESS(Status) && Status != STATUS_NO_MORE_ENTRIES) { DPRINT1("Status: %lx\n", Status); return RtlNtStatusToDosError(Status); } /* Now, we have two cases: * We found the driver: it means it's running * We didn't find the driver: it wasn't running */ if (bFound) { /* Found, return it's running */ dwPreviousState = lpService->Status.dwCurrentState; /* It is running */ lpService->Status.dwCurrentState = SERVICE_RUNNING; if (dwPreviousState == SERVICE_STOPPED) { /* Make it run if it was stopped before */ lpService->Status.dwWin32ExitCode = ERROR_SUCCESS; lpService->Status.dwServiceSpecificExitCode = ERROR_SUCCESS; lpService->Status.dwControlsAccepted = SERVICE_ACCEPT_STOP; lpService->Status.dwCheckPoint = 0; lpService->Status.dwWaitHint = 0; } if (lpService->Status.dwWin32ExitCode == ERROR_SERVICE_NEVER_STARTED) lpService->Status.dwWin32ExitCode = ERROR_SUCCESS; } else { /* Not found, return it's stopped */ if (lpService->Status.dwCurrentState == SERVICE_STOP_PENDING) { /* Stopped successfully */ lpService->Status.dwWin32ExitCode = ERROR_SUCCESS; lpService->Status.dwCurrentState = SERVICE_STOPPED; lpService->Status.dwControlsAccepted = 0; lpService->Status.dwCheckPoint = 0; lpService->Status.dwWaitHint = 0; } else if (lpService->Status.dwCurrentState == SERVICE_STOPPED) { /* Don't change the current status */ } else { lpService->Status.dwWin32ExitCode = ERROR_GEN_FAILURE; lpService->Status.dwCurrentState = SERVICE_STOPPED; lpService->Status.dwControlsAccepted = 0; lpService->Status.dwCheckPoint = 0; lpService->Status.dwWaitHint = 0; } } /* Copy service status if required */ if (lpServiceStatus != NULL) { RtlCopyMemory(lpServiceStatus, &lpService->Status, sizeof(SERVICE_STATUS)); } DPRINT1("ScmGetDriverStatus() done (Error: %lu)\n", dwError); return ERROR_SUCCESS; }
/** * Fetches more data from the file system. * * @returns IPRT status code * @param pThis The directory instance data. */ static int rtDirNtFetchMore(PRTDIRINTERNAL pThis) { Assert(!pThis->fDataUnread); /* * Allocate the buffer the first time around. * We do this in lazy fashion as some users of RTDirOpen will not actually * list any files, just open it for various reasons. * * We also reduce the buffer size for networked devices as the windows 7-8.1, * server 2012, ++ CIFS servers or/and IFSes screws up buffers larger than 64KB. * There is an alternative hack below, btw. We'll leave both in for now. */ bool fFirst = false; if (!pThis->pabBuffer) { pThis->cbBufferAlloc = _256K; if (true) /** @todo skip for known local devices, like the boot device? */ { IO_STATUS_BLOCK Ios2 = RTNT_IO_STATUS_BLOCK_INITIALIZER; FILE_FS_DEVICE_INFORMATION Info = { 0, 0 }; NTSTATUS rcNt2 = NtQueryVolumeInformationFile(pThis->hDir, &Ios2, &Info, sizeof(Info), FileFsDeviceInformation); if ( !NT_SUCCESS(rcNt2) || (Info.Characteristics & FILE_REMOTE_DEVICE) || Info.DeviceType == FILE_DEVICE_NETWORK || Info.DeviceType == FILE_DEVICE_NETWORK_FILE_SYSTEM || Info.DeviceType == FILE_DEVICE_NETWORK_REDIRECTOR || Info.DeviceType == FILE_DEVICE_SMB) pThis->cbBufferAlloc = _64K; } fFirst = false; pThis->pabBuffer = (uint8_t *)RTMemAlloc(pThis->cbBufferAlloc); if (!pThis->pabBuffer) { do { pThis->cbBufferAlloc /= 4; pThis->pabBuffer = (uint8_t *)RTMemAlloc(pThis->cbBufferAlloc); } while (pThis->pabBuffer == NULL && pThis->cbBufferAlloc > _4K); if (!pThis->pabBuffer) return VERR_NO_MEMORY; } /* * Also try determining the device number. */ PFILE_FS_VOLUME_INFORMATION pVolInfo = (PFILE_FS_VOLUME_INFORMATION)pThis->pabBuffer; pVolInfo->VolumeSerialNumber = 0; IO_STATUS_BLOCK Ios = RTNT_IO_STATUS_BLOCK_INITIALIZER; NTSTATUS rcNt = NtQueryVolumeInformationFile(pThis->hDir, &Ios, pVolInfo, RT_MIN(_2K, pThis->cbBufferAlloc), FileFsVolumeInformation); if (NT_SUCCESS(rcNt) && NT_SUCCESS(Ios.Status)) pThis->uDirDev = pVolInfo->VolumeSerialNumber; else pThis->uDirDev = 0; AssertCompile(sizeof(pThis->uDirDev) == sizeof(pVolInfo->VolumeSerialNumber)); /** @todo Grow RTDEV to 64-bit and add low dword of VolumeCreationTime to the top of uDirDev. */ } /* * Read more. */ NTSTATUS rcNt; IO_STATUS_BLOCK Ios = RTNT_IO_STATUS_BLOCK_INITIALIZER; if (pThis->enmInfoClass != (FILE_INFORMATION_CLASS)0) { #ifdef IPRT_WITH_NT_PATH_PASSTHRU if (pThis->enmInfoClass == FileMaximumInformation) { Ios.Information = 0; Ios.Status = rcNt = NtQueryDirectoryObject(pThis->hDir, pThis->pabBuffer, pThis->cbBufferAlloc, RTDIR_NT_SINGLE_RECORD /*ReturnSingleEntry */, pThis->fRestartScan, &pThis->uObjDirCtx, (PULONG)&Ios.Information); } else #endif rcNt = NtQueryDirectoryFile(pThis->hDir, NULL /* Event */, NULL /* ApcRoutine */, NULL /* ApcContext */, &Ios, pThis->pabBuffer, pThis->cbBufferAlloc, pThis->enmInfoClass, RTDIR_NT_SINGLE_RECORD /*ReturnSingleEntry */, pThis->pNtFilterStr, pThis->fRestartScan); } else { /* * The first time around we have to figure which info class we can use * as well as the right buffer size. We prefer an info class which * gives us file IDs (Vista+ IIRC) and we prefer large buffers (for long * ReFS file names and such), but we'll settle for whatever works... * * The windows 7 thru 8.1 CIFS servers have been observed to have * trouble with large buffers, but weirdly only when listing large * directories. Seems 0x10000 is the max. (Samba does not exhibit * these problems, of course.) * * This complicates things. The buffer size issues causes an * STATUS_INVALID_PARAMETER error. Now, you would expect the lack of * FileIdBothDirectoryInformation support to return * STATUS_INVALID_INFO_CLASS, but I'm not entirely sure if we can 100% * depend on third IFSs to get that right. Nor, am I entirely confident * that we can depend on them to check the class before the buffer size. * * Thus the mess. */ if (RT_MAKE_U64(RTNtCurrentPeb()->OSMinorVersion, RTNtCurrentPeb()->OSMajorVersion) > RT_MAKE_U64(0,5) /* > W2K */) pThis->enmInfoClass = FileIdBothDirectoryInformation; /* Introduced in XP, from I can tell. */ else pThis->enmInfoClass = FileBothDirectoryInformation; rcNt = NtQueryDirectoryFile(pThis->hDir, NULL /* Event */, NULL /* ApcRoutine */, NULL /* ApcContext */, &Ios, pThis->pabBuffer, pThis->cbBufferAlloc, pThis->enmInfoClass, RTDIR_NT_SINGLE_RECORD /*ReturnSingleEntry */, pThis->pNtFilterStr, pThis->fRestartScan); if (NT_SUCCESS(rcNt)) { /* likely */ } else { bool fRestartScan = pThis->fRestartScan; for (unsigned iRetry = 0; iRetry < 2; iRetry++) { if ( rcNt == STATUS_INVALID_INFO_CLASS || rcNt == STATUS_INVALID_PARAMETER_8 || iRetry != 0) pThis->enmInfoClass = FileBothDirectoryInformation; uint32_t cbBuffer = pThis->cbBufferAlloc; if ( rcNt == STATUS_INVALID_PARAMETER || rcNt == STATUS_INVALID_PARAMETER_7 || rcNt == STATUS_INVALID_NETWORK_RESPONSE || iRetry != 0) { cbBuffer = RT_MIN(cbBuffer / 2, _64K); fRestartScan = true; } for (;;) { rcNt = NtQueryDirectoryFile(pThis->hDir, NULL /* Event */, NULL /* ApcRoutine */, NULL /* ApcContext */, &Ios, pThis->pabBuffer, cbBuffer, pThis->enmInfoClass, RTDIR_NT_SINGLE_RECORD /*ReturnSingleEntry */, pThis->pNtFilterStr, fRestartScan); if ( NT_SUCCESS(rcNt) || cbBuffer == pThis->cbBufferAlloc || cbBuffer <= sizeof(*pThis->uCurData.pBothId) + sizeof(WCHAR) * 260) break; /* Reduce the buffer size agressivly and try again. We fall back to FindFirstFile values for the final lap. This means we'll do 4 rounds with the current initial buffer size (64KB, 8KB, 1KB, 0x278/0x268). */ cbBuffer /= 8; if (cbBuffer < 1024) cbBuffer = pThis->enmInfoClass == FileIdBothDirectoryInformation ? sizeof(*pThis->uCurData.pBothId) + sizeof(WCHAR) * 260 : sizeof(*pThis->uCurData.pBoth) + sizeof(WCHAR) * 260; } if (NT_SUCCESS(rcNt)) { pThis->cbBufferAlloc = cbBuffer; break; } } } } if (!NT_SUCCESS(rcNt)) { /* Note! VBoxSVR and CIFS file systems both ends up with STATUS_NO_SUCH_FILE here instead of STATUS_NO_MORE_FILES. */ if (rcNt == STATUS_NO_MORE_FILES || rcNt == STATUS_NO_MORE_ENTRIES || rcNt == STATUS_NO_SUCH_FILE) return VERR_NO_MORE_FILES; return RTErrConvertFromNtStatus(rcNt); } pThis->fRestartScan = false; AssertMsg( Ios.Information > (pThis->enmInfoClass == FileMaximumInformation ? sizeof(*pThis->uCurData.pObjDir) : sizeof(*pThis->uCurData.pBoth)), ("Ios.Information=%#x\n", Ios.Information)); /* * Set up the data members. */ pThis->uCurData.u = (uintptr_t)pThis->pabBuffer; pThis->cbBuffer = Ios.Information; int rc = rtDirNtCheckRecord(pThis); pThis->fDataUnread = RT_SUCCESS(rc); return rc; }
void Mutexplorer::Mutexscanner(WCHAR *pszDir) { HANDLE hObj; ULONG ntStatus; OBJECT_ATTRIBUTES ObjectAttributes; POBJDIR_INFORMATION DirObjInformation; UNICODE_STRING UName; char szData[1024*2]; char szBuf[1024*2]; ULONG dw; char szIdentBuf[100]; ULONG index; static int iLevel = 0; // set indent of current level memset(szIdentBuf, ' ', iLevel * 3); szIdentBuf[iLevel * 3] = 0; RtlInitUnicodeString(&UName, pszDir); InitializeObjectAttributes ( &ObjectAttributes, &UName, OBJ_CASE_INSENSITIVE, NULL, NULL ); ntStatus = NtOpenDirectoryObject( &hObj, STANDARD_RIGHTS_READ | DIRECTORY_QUERY, &ObjectAttributes); if(ntStatus == 0) { index = 0; // start index do { memset(szData, 0, sizeof(szData)); DirObjInformation = (POBJDIR_INFORMATION)&szData; ntStatus = NtQueryDirectoryObject( hObj, DirObjInformation, sizeof(szData), TRUE, FALSE, &index, &dw); if(ntStatus == 0) { szBuf[0] = 0; if (wcscmp(DirObjInformation->ObjectTypeName.Buffer,L"Mutant") == 0) { QString mutexName = QString::fromWCharArray(DirObjInformation->ObjectName.Buffer); ui->listWidget->addItem(mutexName); } if(wcscmp(DirObjInformation->ObjectTypeName.Buffer, L"Directory") == 0) { iLevel++; if(wcslen(pszDir) && pszDir[wcslen(pszDir) - 1] == (WCHAR)'\\') { swprintf((WCHAR*)szBuf, L"%s%wZ", pszDir, &DirObjInformation->ObjectName); } else { swprintf((WCHAR*)szBuf, L"%s\\%wZ", pszDir, &DirObjInformation->ObjectName); } Mutexscanner((WCHAR*)szBuf); iLevel--; } } else if(ntStatus == 0) printf("NtQueryDirectoryObject = 0x%lX (%S)\n", ntStatus, pszDir); } while(ntStatus == 0); CloseHandle(hObj); } else printf("NtOpenDirectoryObject = 0x%lX (%S)\n", ntStatus, pszDir); }
void EnumerateObjects(PWSTR strRoot) { NTSTATUS statusNT; HANDLE hDirOb; OBJECT_ATTRIBUTES oaAttrib; int intCount=0; HMODULE hNTDLL = LoadLibrary("ntdll.dll"); NtOpenDirectoryObject = (NTSTATUS (__stdcall *)(HANDLE *, ACCESS_MASK, POBJECT_ATTRIBUTES)) GetProcAddress(hNTDLL,"NtOpenDirectoryObject"); NtQueryDirectoryObject = (NTSTATUS (__stdcall *)(HANDLE, PVOID, ULONG, BOOLEAN, BOOLEAN, PULONG, PULONG)) GetProcAddress(hNTDLL,"NtQueryDirectoryObject"); NtQueryDirectoryFile = (NTSTATUS (__stdcall *)(HANDLE, HANDLE, PIO_APC_ROUTINE, PVOID, PIO_STATUS_BLOCK, PVOID, ULONG, FILE_INFORMATION_CLASS, BOOLEAN, PUNICODE_STRING, BOOLEAN)) GetProcAddress(hNTDLL,"NtQueryDirectoryFile"); oaAttrib.Length = 6*4; oaAttrib.RootDirectory = 0; oaAttrib.ObjectName = (PUNICODE_STRING)malloc(sizeof(UNICODE_STRING)); /* ObjectName is a UNICODE_STRING of fixed size */ oaAttrib.Attributes = 0; oaAttrib.a = 0; oaAttrib.b = 0; oaAttrib.ObjectName->Length = (USHORT)wcslen(strRoot)*2; oaAttrib.ObjectName->MaximumLength = (USHORT)wcslen(strRoot)*2+2; oaAttrib.ObjectName->Buffer = strRoot; statusNT = NtOpenDirectoryObject(&hDirOb,DIRECTORY_ALL_ACCESS,&oaAttrib); if (statusNT != STATUS_SUCCESS) { return; } UCHAR *strBuffer = (UCHAR*)malloc(1048576); // lovely ULONG uContext=0; ULONG uRetlen; statusNT = NtQueryDirectoryObject(hDirOb,strBuffer,1048576,false,false,&uContext,&uRetlen); UNICODE_STRING *pstrName = (PUNICODE_STRING)strBuffer; for(intCount=0;pstrName[intCount].Length != 0;intCount+=2) { TCHAR strFullpath[MAX_PATH]; sprintf_s(strFullpath,"\\\\.\\%ws",pstrName[intCount].Buffer); if (wcscmp(pstrName[intCount+1].Buffer,L"Directory") == 0 || wcscmp(pstrName[intCount+1].Buffer,L"SymbolicLink") == 0) { if (wcsstr(strRoot,pstrName[intCount].Buffer) != NULL) break; TCHAR strNewroot[MAX_PATH]; _tcscpy_s(strNewroot,strRoot); if (wcscmp(strRoot,L"\\") != 0) _tcscat_s(strNewroot,L"\\"); _tcscat_s(strNewroot,pstrName[intCount].Buffer); EnumerateObjects(strNewroot); } } CloseHandle(hDirOb); if (oaAttrib.ObjectName !=NULL) free(oaAttrib.ObjectName); if (strBuffer !=NULL) free(strBuffer); }
DWORD ScmGetDriverStatus(PSERVICE lpService, LPSERVICE_STATUS lpServiceStatus) { OBJECT_ATTRIBUTES ObjectAttributes; UNICODE_STRING DirName; HANDLE DirHandle; NTSTATUS Status = STATUS_SUCCESS; POBJECT_DIRECTORY_INFORMATION DirInfo; ULONG BufferLength; ULONG DataLength; ULONG Index; DWORD dwError = ERROR_SUCCESS; BOOLEAN bFound = FALSE; DPRINT1("ScmGetDriverStatus() called\n"); memset(lpServiceStatus, 0, sizeof(SERVICE_STATUS)); if (lpService->Status.dwServiceType == SERVICE_KERNEL_DRIVER) { RtlInitUnicodeString(&DirName, L"\\Driver"); } else // if (lpService->Status.dwServiceType == SERVICE_FILE_SYSTEM_DRIVER) { ASSERT(lpService->Status.dwServiceType == SERVICE_FILE_SYSTEM_DRIVER); RtlInitUnicodeString(&DirName, L"\\FileSystem"); } InitializeObjectAttributes(&ObjectAttributes, &DirName, 0, NULL, NULL); Status = NtOpenDirectoryObject(&DirHandle, DIRECTORY_QUERY | DIRECTORY_TRAVERSE, &ObjectAttributes); if (!NT_SUCCESS(Status)) { DPRINT1("NtOpenDirectoryObject() failed!\n"); return RtlNtStatusToDosError(Status); } BufferLength = sizeof(OBJECT_DIRECTORY_INFORMATION) + 2 * MAX_PATH * sizeof(WCHAR); DirInfo = (OBJECT_DIRECTORY_INFORMATION*) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, BufferLength); Index = 0; while (TRUE) { Status = NtQueryDirectoryObject(DirHandle, DirInfo, BufferLength, TRUE, FALSE, &Index, &DataLength); if (Status == STATUS_NO_MORE_ENTRIES) { DPRINT("No more services\n"); break; } if (!NT_SUCCESS(Status)) break; DPRINT("Comparing: '%S' '%wZ'\n", lpService->lpServiceName, &DirInfo->Name); if (_wcsicmp(lpService->lpServiceName, DirInfo->Name.Buffer) == 0) { DPRINT1("Found: '%S' '%wZ'\n", lpService->lpServiceName, &DirInfo->Name); bFound = TRUE; break; } } HeapFree(GetProcessHeap(), 0, DirInfo); NtClose(DirHandle); if (!NT_SUCCESS(Status)) { DPRINT1("Status: %lx\n", Status); return RtlNtStatusToDosError(Status); } if ((bFound == TRUE) && (lpService->Status.dwCurrentState != SERVICE_STOP_PENDING)) { if (lpService->Status.dwCurrentState == SERVICE_STOPPED) { lpService->Status.dwWin32ExitCode = ERROR_SUCCESS; lpService->Status.dwServiceSpecificExitCode = ERROR_SUCCESS; lpService->Status.dwCheckPoint = 0; lpService->Status.dwWaitHint = 0; lpService->Status.dwControlsAccepted = 0; } else { lpService->Status.dwCurrentState = SERVICE_RUNNING; lpService->Status.dwControlsAccepted = SERVICE_ACCEPT_STOP; if (lpService->Status.dwWin32ExitCode == ERROR_SERVICE_NEVER_STARTED) lpService->Status.dwWin32ExitCode = ERROR_SUCCESS; } } else { lpService->Status.dwCurrentState = SERVICE_STOPPED; lpService->Status.dwControlsAccepted = 0; lpService->Status.dwCheckPoint = 0; lpService->Status.dwWaitHint = 0; if (lpService->Status.dwCurrentState == SERVICE_STOP_PENDING) lpService->Status.dwWin32ExitCode = ERROR_SUCCESS; else lpService->Status.dwWin32ExitCode = ERROR_GEN_FAILURE; } if (lpServiceStatus != NULL) { memcpy(lpServiceStatus, &lpService->Status, sizeof(SERVICE_STATUS)); } DPRINT1("ScmGetDriverStatus() done (Error: %lu)\n", dwError); return ERROR_SUCCESS; }
HRESULT EnumerateNext(LPITEMIDLIST* ppidl) { BYTE dirbuffer[2048]; if (!NT_SUCCESS(NtQueryDirectoryObject(m_directory, dirbuffer, 2048, TRUE, m_first, &m_enumContext, NULL))) return S_FALSE; m_first = FALSE; // if ppidl is NULL, assume the caller was Skip(), // so we don't care about the info if (!ppidl) return S_OK; POBJECT_DIRECTORY_INFORMATION info = (POBJECT_DIRECTORY_INFORMATION) dirbuffer; if (info->Name.Buffer) { StringCbCopyNW(m_pend, sizeof(buffer), info->Name.Buffer, info->Name.Length); } OBJECT_TYPE otype = MapTypeNameToType(info->TypeName.Buffer, info->TypeName.Length); DWORD entryBufferLength = FIELD_OFFSET(NtPidlEntry, entryName) + sizeof(WCHAR); if (info->Name.Buffer) entryBufferLength += info->Name.Length; if (otype < 0) { entryBufferLength += FIELD_OFFSET(NtPidlTypeData, typeName) + sizeof(WCHAR); if (info->TypeName.Buffer) { entryBufferLength += info->TypeName.Length; } } // allocate space for the terminator entryBufferLength += FIELD_OFFSET(SHITEMID, abID); NtPidlEntry* entry = (NtPidlEntry*) CoTaskMemAlloc(entryBufferLength); if (!entry) return E_OUTOFMEMORY; memset(entry, 0, entryBufferLength); entry->cb = FIELD_OFFSET(NtPidlEntry, entryName); entry->magic = NT_OBJECT_PIDL_MAGIC; entry->objectType = otype; if (info->Name.Buffer) { entry->entryNameLength = info->Name.Length; StringCbCopyNW(entry->entryName, entryBufferLength, info->Name.Buffer, info->Name.Length); entry->cb += entry->entryNameLength + sizeof(WCHAR); } else { entry->entryNameLength = 0; entry->entryName[0] = 0; entry->cb += sizeof(WCHAR); } if (otype < 0) { NtPidlTypeData * typedata = (NtPidlTypeData*) ((PBYTE) entry + entry->cb); DWORD remainingSpace = entryBufferLength - ((PBYTE) (typedata->typeName) - (PBYTE) entry); if (info->TypeName.Buffer) { typedata->typeNameLength = info->TypeName.Length; StringCbCopyNW(typedata->typeName, remainingSpace, info->TypeName.Buffer, info->TypeName.Length); entry->cb += typedata->typeNameLength + sizeof(WCHAR); } else { typedata->typeNameLength = 0; typedata->typeName[0] = 0; entry->cb += typedata->typeNameLength + sizeof(WCHAR); } } *ppidl = (LPITEMIDLIST) entry; return S_OK; }