|
|
/*++
Copyright (c) 1989-2000 Microsoft Corporation
Module Name:
ntKMode.c
Abstract:
This module implements low level primitives for kernel mode implementation.
Author:
VadimB created sometime in 2000
Revision History:
--*/
#include "sdbp.h"
#ifdef KERNEL_MODE
extern TAG g_rgDirectoryTags[];
#ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGE, SdbTagIDToTagRef)
#pragma alloc_text(PAGE, SdbTagRefToTagID)
#pragma alloc_text(PAGE, SdbInitDatabaseInMemory)
#pragma alloc_text(PAGE, SdbpOpenAndMapFile)
#pragma alloc_text(PAGE, SdbpUnmapAndCloseFile)
#pragma alloc_text(PAGE, SdbpUpcaseUnicodeStringToMultiByteN)
#pragma alloc_text(PAGE, SdbpQueryFileDirectoryAttributesNT)
#pragma alloc_text(PAGE, SdbpDoesFileExists_U)
#pragma alloc_text(PAGE, SdbGetFileInfo)
#pragma alloc_text(PAGE, DuplicateUnicodeString)
#pragma alloc_text(PAGE, SdbpCreateUnicodeString)
#pragma alloc_text(PAGE, SdbpGetFileDirectoryAttributesNT)
#endif
BOOL SdbTagIDToTagRef( IN HSDB hSDB, IN PDB pdb, // PDB the TAGID is from
IN TAGID tiWhich, // TAGID to convert
OUT TAGREF* ptrWhich // converted TAGREF
) /*++
Return: TRUE if a TAGREF was found, FALSE otherwise.
Desc: Converts a PDB and TAGID into a TAGREF, by packing the high bits of the TAGREF with a constant that tells us which PDB, and the low bits with the TAGID. --*/ { PSDBCONTEXT pSdbContext = (PSDBCONTEXT)hSDB; BOOL bReturn = FALSE;
//
// In kernel mode we only support sysmain db
//
*ptrWhich = tiWhich | PDB_MAIN; bReturn = TRUE;
if (!bReturn) { DBGPRINT((sdlError, "SdbTagIDToTagRef", "Bad PDB.\n")); *ptrWhich = TAGREF_NULL; }
return bReturn; }
BOOL SdbTagRefToTagID( IN HSDB hSDB, IN TAGREF trWhich, // TAGREF to convert
OUT PDB* ppdb, // PDB the TAGREF is from
OUT TAGID* ptiWhich // TAGID within that PDB
) /*++
Return: TRUE if the TAGREF is valid and was converted, FALSE otherwise.
Desc: Converts a TAGREF type to a TAGID and a PDB. This manages the interface between NTDLL, which knows nothing of PDBs, and the shimdb, which manages three separate PDBs. The TAGREF incorporates the TAGID and a constant that tells us which PDB the TAGID is from. In this way, the NTDLL client doesn't need to know which DB the info is coming from. --*/ { PSDBCONTEXT pSdbContext = (PSDBCONTEXT)hSDB; BOOL bReturn = TRUE; TAGID tiWhich = TAGID_NULL; PDB pdb = NULL; DWORD dwMask;
dwMask = trWhich & TAGREF_STRIP_PDB; if (dwMask != PDB_MAIN) { goto cleanup; }
tiWhich = trWhich & TAGREF_STRIP_TAGID; pdb = pSdbContext->pdbMain; //
// See that we double-check here
//
if (pdb == NULL && tiWhich != TAGID_NULL) { DBGPRINT((sdlError, "SdbTagRefToTagID", "PDB dereferenced by this TAGREF is NULL\n")); bReturn = FALSE; }
cleanup:
if (ppdb != NULL) { *ppdb = pdb; }
if (ptiWhich != NULL) { *ptiWhich = tiWhich; }
return bReturn; }
HSDB SdbInitDatabaseInMemory( IN LPVOID pDatabaseImage, IN DWORD dwImageSize ) /*++
Return: BUGBUG: ?
Desc: BUGBUG: ? --*/ { PSDBCONTEXT pContext;
//
// Initialize the context.
//
pContext = (PSDBCONTEXT)SdbAlloc(sizeof(SDBCONTEXT)); if (pContext == NULL) { DBGPRINT((sdlError, "SdbInitDatabaseInMemory", "Failed to allocate %d bytes for HSDB\n", sizeof(SDBCONTEXT))); return NULL; }
//
// Now open the database.
//
pContext->pdbMain = SdbpOpenDatabaseInMemory(pDatabaseImage, dwImageSize); if (pContext->pdbMain == NULL) { DBGPRINT((sdlError, "SdbInitDatabaseInMemory", "Unable to open main database at 0x%x size 0x%x\n", pDatabaseImage, dwImageSize)); goto ErrHandle; }
return (HSDB)pContext;
ErrHandle:
if (pContext != NULL) {
if (pContext->pdbMain != NULL) { SdbCloseDatabaseRead(pContext->pdbMain); }
SdbFree(pContext); }
return NULL; }
//
// Open and map File
//
BOOL SdbpOpenAndMapFile( IN LPCWSTR szPath, // pointer to the fully-qualified filename
OUT PIMAGEFILEDATA pImageData, // pointer to IMAGEFILEDATA that receives
// image-related information
IN PATH_TYPE ePathType // ignored
) /*++
Return: TRUE on success, FALSE otherwise.
Desc: Opens a file and maps it into memory. --*/ {
NTSTATUS Status; OBJECT_ATTRIBUTES ObjectAttributes; UNICODE_STRING ustrFileName; HANDLE hSection = NULL; HANDLE hFile = INVALID_HANDLE_VALUE; IO_STATUS_BLOCK IoStatusBlock; SIZE_T ViewSize = 0; PVOID pBase = NULL; DWORD dwFlags = 0;
FILE_STANDARD_INFORMATION StandardInfo;
if (pImageData->dwFlags & IMAGEFILEDATA_PBASEVALID) { //
// special case, only headers are valid in our assumption
//
return TRUE; }
//
// Initialize return data
//
if (pImageData->dwFlags & IMAGEFILEDATA_HANDLEVALID) { hFile = pImageData->hFile; if (hFile != INVALID_HANDLE_VALUE) { dwFlags |= IMAGEFILEDATA_NOFILECLOSE; } } RtlZeroMemory(pImageData, sizeof(*pImageData)); pImageData->hFile = INVALID_HANDLE_VALUE;
if (hFile == INVALID_HANDLE_VALUE) {
//
// Open the file
//
RtlInitUnicodeString(&ustrFileName, szPath);
InitializeObjectAttributes(&ObjectAttributes, &ustrFileName, OBJ_CASE_INSENSITIVE, NULL, NULL);
Status = ZwCreateFile(&hFile, GENERIC_READ, &ObjectAttributes, &IoStatusBlock, NULL, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ, FILE_OPEN, FILE_SYNCHRONOUS_IO_NONALERT|FILE_NON_DIRECTORY_FILE, NULL, 0);
if (!NT_SUCCESS(Status)) { DBGPRINT((sdlError, "SdbpOpenAndMapFile", "ZwCreateFile failed status 0x%x\n", Status)); return FALSE; }
}
//
// Query file size
//
Status = ZwQueryInformationFile(hFile, &IoStatusBlock, &StandardInfo, sizeof(StandardInfo), FileStandardInformation); if (!NT_SUCCESS(Status)) { DBGPRINT((sdlError, "SdbpOpenAndMapFile", "ZwQueryInformationFile (EOF) failed Status 0x%x\n", Status)); if (!(dwFlags & IMAGEFILEDATA_NOFILECLOSE)) { ZwClose(hFile); } return FALSE; }
InitializeObjectAttributes(&ObjectAttributes, NULL, OBJ_CASE_INSENSITIVE, NULL, NULL);
Status = ZwCreateSection(&hSection, STANDARD_RIGHTS_REQUIRED | SECTION_QUERY | SECTION_MAP_READ, &ObjectAttributes, NULL, PAGE_READONLY, SEC_COMMIT, hFile);
if (!NT_SUCCESS(Status)) { DBGPRINT((sdlError, "SdbpOpenAndMapFile", "ZwOpenSectionFailed status 0x%x\n", Status)); if (!(dwFlags & IMAGEFILEDATA_NOFILECLOSE)) { ZwClose(hFile); } return FALSE; }
Status = ZwMapViewOfSection(hSection, NtCurrentProcess(), &pBase, 0L, 0L, NULL, &ViewSize, ViewUnmap, 0L, PAGE_READONLY);
if (!NT_SUCCESS(Status)) { DBGPRINT((sdlError, "SdbpMapFile", "NtMapViewOfSection failed Status 0x%x\n", Status));
ZwClose(hSection); if (!(dwFlags & IMAGEFILEDATA_NOFILECLOSE)) { ZwClose(hFile); } return FALSE; }
pImageData->hFile = hFile; pImageData->dwFlags = dwFlags; pImageData->hSection = hSection; pImageData->pBase = pBase; pImageData->ViewSize = ViewSize; pImageData->FileSize = StandardInfo.EndOfFile.QuadPart;
return TRUE; }
BOOL SdbpUnmapAndCloseFile( IN PIMAGEFILEDATA pImageData // pointer to IMAGEFILEDATE - image-related information
) /*++
Return: TRUE on success, FALSE otherwise.
Desc: Closes and unmaps an opened file. --*/ { BOOL bSuccess = TRUE; NTSTATUS Status;
if (pImageData->dwFlags & IMAGEFILEDATA_PBASEVALID) { // externally supplied pointer
RtlZeroMemory(pImageData, sizeof(*pImageData)); return TRUE; }
if (pImageData->pBase != NULL) { Status = ZwUnmapViewOfSection(NtCurrentProcess(), pImageData->pBase); if (!NT_SUCCESS(Status)) { bSuccess = FALSE; DBGPRINT((sdlError, "SdbpCloseAndUnmapFile", "ZwUnmapViewOfSection failed Status 0x%x\n", Status)); } pImageData->pBase = NULL; }
if (pImageData->hSection != NULL) { Status = ZwClose(pImageData->hSection); if (!NT_SUCCESS(Status)) { bSuccess = FALSE; DBGPRINT((sdlError, "SdbpCloseAndUnmapFile", "ZwClose on section failed Status 0x%x\n", Status)); }
pImageData->hSection = NULL; }
if (pImageData->dwFlags & IMAGEFILEDATA_NOFILECLOSE) {
pImageData->hFile = INVALID_HANDLE_VALUE;
} else {
if (pImageData->hFile != INVALID_HANDLE_VALUE) { Status = ZwClose(pImageData->hFile); if (!NT_SUCCESS(Status)) { bSuccess = FALSE; DBGPRINT((sdlError, "SdbpCloseAndUnmapFile", "ZwClose on file failed Status 0x%x\n", Status)); }
pImageData->hFile = INVALID_HANDLE_VALUE; } }
return bSuccess; }
NTSTATUS SdbpUpcaseUnicodeStringToMultiByteN( OUT LPSTR lpszDest, // dest buffer
IN DWORD dwSize, // size in characters, excluding unicode_null
IN LPCWSTR lpszSrc // source
) /*++
Return: TRUE on success, FALSE otherwise.
Desc: Convert up to dwSize characters from Unicode to ANSI. --*/ { ANSI_STRING strDest; UNICODE_STRING ustrSource; NTSTATUS Status; UNICODE_STRING ustrUpcaseSource = { 0 }; USHORT DestBufSize = (USHORT)dwSize * sizeof(WCHAR);
RtlInitUnicodeString(&ustrSource, lpszSrc);
STACK_ALLOC(ustrUpcaseSource.Buffer, ustrSource.MaximumLength);
if (ustrUpcaseSource.Buffer == NULL) { DBGPRINT((sdlError, "SdbpUnicodeToMultiByteN", "Failed to allocate %d bytes on the stack\n", (DWORD)ustrSource.MaximumLength)); return STATUS_NO_MEMORY; }
ustrUpcaseSource.MaximumLength = ustrSource.MaximumLength; ustrUpcaseSource.Length = 0;
Status = RtlUpcaseUnicodeString(&ustrUpcaseSource, &ustrSource, FALSE); if (!NT_SUCCESS(Status)) { DBGPRINT((sdlError, "SdbpUnicodeToMultiByteN", "RtlUpcaseUnicodeString failed Status 0x%x\n", Status)); goto Done; }
if (ustrUpcaseSource.Length > DestBufSize) { ustrUpcaseSource.Length = DestBufSize; }
strDest.Buffer = lpszDest; strDest.MaximumLength = DestBufSize + sizeof(UNICODE_NULL); strDest.Length = 0;
Status = RtlUnicodeStringToAnsiString(&strDest, &ustrUpcaseSource, FALSE); if (!NT_SUCCESS(Status)) { DBGPRINT((sdlError, "SdbpUnicodeToMultiByteN", "RtlUnicodeStringToAnsiString failed Status 0x%x\n", Status)); }
Done:
if (ustrUpcaseSource.Buffer != NULL) { STACK_FREE(ustrUpcaseSource.Buffer); }
return Status; }
BOOL SdbpQueryFileDirectoryAttributesNT( PIMAGEFILEDATA pImageData, PFILEDIRECTORYATTRIBUTES pFileDirectoryAttributes ) /*++
Return: TRUE on success, FALSE otherwise.
Desc: BUGBUG: ? --*/ { LARGE_INTEGER liFileSize;
liFileSize.QuadPart = pImageData->FileSize;
pFileDirectoryAttributes->dwFlags |= FDA_FILESIZE; pFileDirectoryAttributes->dwFileSizeHigh = liFileSize.HighPart; pFileDirectoryAttributes->dwFileSizeLow = liFileSize.LowPart;
return TRUE; }
BOOL SdbpDoesFileExists_U( LPCWSTR pwszPath ) /*++
Return: TRUE on success, FALSE otherwise.
Desc: BUGBUG: ? --*/ { OBJECT_ATTRIBUTES ObjectAttributes; UNICODE_STRING ustrFileName; HANDLE hFile; NTSTATUS Status; IO_STATUS_BLOCK IoStatusBlock;
RtlInitUnicodeString(&ustrFileName, pwszPath);
InitializeObjectAttributes(&ObjectAttributes, &ustrFileName, OBJ_CASE_INSENSITIVE, NULL, NULL);
Status = ZwCreateFile(&hFile, STANDARD_RIGHTS_REQUIRED | FILE_READ_ATTRIBUTES, &ObjectAttributes, &IoStatusBlock, NULL, // AllocationSize
FILE_ATTRIBUTE_NORMAL, // FileAttributes
FILE_SHARE_READ, // Share Access
FILE_OPEN, // Create Disposition
FILE_NON_DIRECTORY_FILE | // Create Options
FILE_SYNCHRONOUS_IO_NONALERT, NULL, // EaBuffer
0); // EaLength
if (!NT_SUCCESS(Status)) { DBGPRINT((sdlError, "SdbpDoesFileExists_U", "Failed to create file. Status 0x%x\n", Status)); return FALSE; }
ZwClose(hFile);
return TRUE; }
PVOID SdbGetFileInfo( IN HSDB hSDB, IN LPCWSTR pwszFilePath, IN HANDLE hFile, // handle for the file in question
IN LPVOID pImageBase, // image base for this file
IN DWORD dwImageSize, IN BOOL bNoCache ) /*++
Return: BUGBUG: ?
Desc: Create and link a new entry in a file attribute cache. --*/ { PSDBCONTEXT pContext = (PSDBCONTEXT)hSDB; LPCWSTR FullPath = pwszFilePath; NTSTATUS Status; PFILEINFO pFileInfo = NULL; UNICODE_STRING FullPathU;
if (!bNoCache) { pFileInfo = FindFileInfo(pContext, FullPath); }
if (pFileInfo == NULL) { if (hFile != INVALID_HANDLE_VALUE || pImageBase != NULL || SdbpDoesFileExists_U(FullPath)) { RtlInitUnicodeString(&FullPathU, FullPath);
pFileInfo = CreateFileInfo(pContext, FullPathU.Buffer, FullPathU.Length / sizeof(WCHAR), hFile, pImageBase, dwImageSize, bNoCache); } }
return (PVOID)pFileInfo; }
WCHAR* DuplicateUnicodeString( PUNICODE_STRING pStr, PUSHORT pLength // pLength is an allocated length
) /*++
Return: BUGBUG: ?
Desc: BUGBUG: ? --*/ { WCHAR* pBuffer = NULL; USHORT Length = 0;
if (pStr != NULL && pStr->Length > 0) {
Length = pStr->Length + sizeof(UNICODE_NULL);
pBuffer = (WCHAR*)SdbAlloc(Length);
if (pBuffer == NULL) { DBGPRINT((sdlError, "DuplicateUnicodeString", "Failed to allocate %d bytes\n", Length)); return NULL; }
RtlMoveMemory(pBuffer, pStr->Buffer, pStr->Length); pBuffer[pStr->Length/sizeof(WCHAR)] = UNICODE_NULL; }
if (pLength != NULL) { *pLength = Length; }
return pBuffer; }
BOOL SdbpCreateUnicodeString( PUNICODE_STRING pStr, LPCWSTR lpwsz ) /*++
Return: BUGBUG: ?
Desc: BUGBUG: ? --*/ { USHORT Length; UNICODE_STRING ustrSrc;
RtlZeroMemory(pStr, sizeof(*pStr)); RtlInitUnicodeString(&ustrSrc, lpwsz);
pStr->Buffer = DuplicateUnicodeString(&ustrSrc, &Length); pStr->Length = ustrSrc.Length; pStr->MaximumLength = Length;
return pStr->Buffer != NULL; }
BOOL SdbpGetFileDirectoryAttributesNT( OUT PFILEINFO pFileInfo, IN PIMAGEFILEDATA pImageData ) /*++
Return: TRUE on success, FALSE otherwise.
Desc: This function retrieves the header attributes for the specified file. --*/ { BOOL bSuccess = FALSE; FILEDIRECTORYATTRIBUTES fda; int i;
bSuccess = SdbpQueryFileDirectoryAttributesNT(pImageData, &fda); if (!bSuccess) { DBGPRINT((sdlInfo, "SdbpGetFileDirectoryAttributesNT", "No file directory attributes available.\n")); goto Done; }
if (fda.dwFlags & FDA_FILESIZE) { assert(fda.dwFileSizeHigh == 0); SdbpSetAttribute(pFileInfo, TAG_SIZE, &fda.dwFileSizeLow); }
Done:
if (!bSuccess) { for (i = 0; g_rgDirectoryTags[i] != 0; ++i) { SdbpSetAttribute(pFileInfo, g_rgDirectoryTags[i], NULL); } }
return bSuccess; }
#ifdef _DEBUG_SPEW
extern DBGLEVELINFO g_rgDbgLevelInfo[]; extern PCH g_szDbgLevelUser; #endif // _DEBUG_SPEW
int __cdecl ShimDbgPrint( int iLevel, PCH pszFunctionName, PCH Format, ... ) { int nch = 0;
#ifdef _DEBUG_SPEW
PCH pszFormat = NULL; va_list arglist; ULONG Level = 0; int i; CHAR szPrefix[64]; PCH pchBuffer = szPrefix; PCH pchLevel = NULL;
PREPARE_FORMAT(pszFormat, Format);
if (pszFormat == NULL) { //
// Can't convert format for debug output
//
return 0; }
//
// Do we have a comment for this debug level? if so, print it
//
for (i = 0; i < DEBUG_LEVELS; ++i) { if (g_rgDbgLevelInfo[i].iLevel == iLevel) { pchLevel = (PCH)g_rgDbgLevelInfo[i].szStrTag; break; } }
if (pchLevel == NULL) { pchLevel = g_szDbgLevelUser; }
nch = sprintf(pchBuffer, "[%-4hs]", pchLevel); pchBuffer += nch;
if (pszFunctionName) { //
// Single-byte char going into UNICODE buffer
//
nch = sprintf(pchBuffer, "[%-30hs] ", pszFunctionName); pchBuffer += nch; }
switch (iLevel) { case sdlError: Level = (1 << DPFLTR_ERROR_LEVEL) | DPFLTR_MASK; break;
case sdlWarning: Level = (1 << DPFLTR_WARNING_LEVEL) | DPFLTR_MASK; break;
case sdlInfo: Level = (1 << DPFLTR_TRACE_LEVEL) | DPFLTR_MASK; break; }
va_start(arglist, Format);
nch = (int)vDbgPrintExWithPrefix(szPrefix, DPFLTR_NTOSPNP_ID, Level, pszFormat, arglist);
va_end(arglist); STACK_FREE(pszFormat);
#endif // _DEBUG_SPEW
return nch; }
#endif // KERNEL_MODE
|