page06ntfileinfo.cpp

来自「This ZIP archive includes the sources (a」· C++ 代码 · 共 1,751 行 · 第 1/5 页

CPP
1,751
字号
                pliValue->LowPart = (ULONG)StrToInt(szItemText + 1, &szItemText, 16);
            }
            else
            {
                pliValue->HighPart = 0;
                pliValue->LowPart = ulValue;
            }

            return (*szItemText == 0) ? ERROR_SUCCESS : ERROR_BAD_FORMAT;
        }

        case TYPE_FRI_NAME:
        {
            PFILE_RENAME_INFORMATION FileInfo;

            // We have to take the whole structure and get the length
            // (the name must not be zero terminated)
            FileInfo = (PFILE_RENAME_INFORMATION)
                       (pMember->pDataPtr - FIELD_OFFSET(FILE_RENAME_INFORMATION, FileName));

            FileInfo->FileNameLength = (ULONG)(wcslen(szItemText) * sizeof(WCHAR));
            memcpy(FileInfo->FileName, szItemText, FileInfo->FileNameLength);
            return ERROR_SUCCESS;
        }
    }

    return ERROR_NOT_SUPPORTED;
}


static HTREEITEM InsertTreeItemByDataType(
    HWND hTreeView,
    HTREEITEM hParentItem,
    TStructMember * pMember,
    PBYTE pDataPtr)
{
    TStructMember * pMemberInfo = new TStructMember;
    HTREEITEM hNewItem = NULL;
    TCHAR szItemText[1024] = _T("");

    // Fill the item data structure
    pMemberInfo->szMemberName = pMember->szMemberName;
    pMemberInfo->nDataType    = pMember->nDataType;
    pMemberInfo->nMemberSize  = pMember->nMemberSize;
    pMemberInfo->pDataPtr     = pDataPtr;

    // Get the item text
    if(DataToItemText(pMemberInfo, szItemText, _tsize(szItemText), TRUE) == ERROR_SUCCESS)
        hNewItem = InsertTreeItem(hTreeView, hParentItem, szItemText, pMemberInfo);

    return hNewItem;
}

static int GetStructLength(TStructMember * pMember)
{
    int nStructLength = 0;

    // We don't need recursion here; structure members in structures
    // have also their size present, so we just add it
    for(; pMember->szMemberName != NULL; pMember++)
        nStructLength += pMember->nMemberSize;

    // If the structure size is greater than 4 bytes,
    // we have to align it to 8-byte boundary
    if(nStructLength > 0x04)
        nStructLength = ALIGN_INT64(nStructLength);

    return nStructLength;
}

static int ReloadTreeViewItems(HWND hDlg, HWND hTreeView, HTREEITEM hParentItem)
{
    TStructMember * pMemberInfo;
    HTREEITEM hItem = TreeView_GetNextItem(hTreeView, hParentItem, TVGN_CHILD);
    TVITEM tvi;
    TCHAR szItemText[1024];

    ZeroMemory(&tvi, sizeof(TVITEM));

    // Process all items at the same level
    while(hItem != NULL)
    {
        // Retrieve data struct associated with treeview item
        tvi.mask  = TVIF_PARAM;
        tvi.hItem = hItem;
        tvi.lParam = 0;
        TreeView_GetItem(hTreeView, &tvi);
        pMemberInfo = (TStructMember *)tvi.lParam;

        // If any structure associated, get its text
        if(pMemberInfo != NULL)
        {
            // Get the item text
            if(DataToItemText(pMemberInfo, szItemText, _tsize(szItemText), TRUE) == ERROR_SUCCESS)
            {
                tvi.mask    = TVIF_TEXT;
                tvi.pszText = szItemText;
                TreeView_SetItem(hTreeView, &tvi);
            }
        }

        // If the tree view item has a subitem, we have to recursively
        // reload subtree too
        if(TreeView_GetNextItem(hTreeView, hItem, TVGN_CHILD) != NULL)
            ReloadTreeViewItems(hDlg, hTreeView, hItem);

        // And finally, move to the next item at the same level
        hItem = TreeView_GetNextItem(hTreeView, hItem, TVGN_NEXT);
    }

    return TRUE;
}


static int FillStructureMembers(
    HWND hTreeView,
    HTREEITEM hParentItem,
    TStructMember * pMembers,
    LPBYTE pbData)
{
    int nTotalLength = 0;               // Length, in bytes, of the structure member

    for(; pMembers->szMemberName != NULL; pMembers++)
    {
        int nDataLength = 0;

        if(pMembers->nDataType == TYPE_STRUCT)
        {
            HTREEITEM hSubItem;

            assert(pMembers->pSubItems != NULL);

            hSubItem = InsertTreeItem(hTreeView, hParentItem, pMembers->szMemberName, NULL);
            nDataLength = FillStructureMembers(hTreeView, hSubItem, pMembers->pSubItems, pbData);
        }
        else
        {
            InsertTreeItemByDataType(hTreeView, hParentItem, pMembers, pbData);
            nDataLength = pMembers->nMemberSize;
        }

        // Move the data pointer and total length by the item size
        nTotalLength += nDataLength;
        pbData += nDataLength;
    }

    // If the structure size is greater than 4 bytes,
    // we have to align it to 8-byte boundary
    if(nTotalLength > 0x04)
        nTotalLength = ALIGN_INT64(nTotalLength);

    // At the end, we have to round the structure size up to 8-byte boundary
    TreeView_Expand(hTreeView, hParentItem, TVE_EXPAND);
    return nTotalLength;
}

// This function fills a variable length structure
// The data structure must contain "ULONG NextEntryOffset"
// as its very first member

static int FillVarLengthStructMembers(
    HWND hTreeView,
    HTREEITEM hParentItem,
    TStructMember * pMembers,
    LPBYTE pbData)
{
    HTREEITEM hItem;
    TCHAR szItemName[128];
    ULONG NextEntryOffset;
    int nStructLength = 0;
    int nDataLength = 0;
    int nIndex = 0;

    // Insert infos about the streams
    do
    {
        NextEntryOffset = *(PULONG)pbData;

        _stprintf(szItemName, _T("[%u]"), nIndex++);
        hItem = InsertTreeItem(hTreeView, hParentItem, szItemName, pbData);
        nStructLength = FillStructureMembers(hTreeView, hItem, pMembers, pbData);

        // Move to the next structure by simply adding the NextEntryOffset
        // to the current pointer. Also add NextEntryOffset to data size 
        nDataLength += (NextEntryOffset != 0) ? NextEntryOffset : nStructLength;
        pbData += NextEntryOffset;
    }
    while(NextEntryOffset != 0);

    // At the end, we have to round the structure size up to 8-byte boundary
    // Return the total length of the stream info
    TreeView_Expand(hTreeView, hParentItem, TVE_EXPAND);
    return nDataLength;
}


static int FillDialogWithFileInfo(HWND hDlg, FILE_INFORMATION_CLASS FileInfoClass)
{
    TPropSheetData * pData = (TPropSheetData *)GetWindowLongPtr(hDlg, DWLP_USER);
    TFileInfoData * pFileInfoData;
    HTREEITEM hRootItem = NULL;
    HWND hTreeView = GetDlgItem(hDlg, IDC_FILE_INFO);
    HWND hComment = GetDlgItem(hDlg, IDC_COMMENT);
    UINT nInputLength = 0;
    BOOL bEnable = FALSE;
    BOOL bShowTreeView = FALSE;
    int nIndex = (int)FileInfoClass - 1;

    // Delete all items in the tree view
    TreeView_DeleteAllItems(hTreeView);

    // Fill the tree view.
    // For some structures (like FILE_STREAM_INFORMATION),
    // we have to do it manually, because our data struct description
    // don't allow us to process the variable structs following each other

    pFileInfoData = &FileInfoData[nIndex];
    if(pFileInfoData->szStructName != NULL)
    {
        hRootItem = InsertTreeItem(hTreeView, TVI_ROOT, pFileInfoData->szStructName, NULL);
        if(hRootItem != NULL && pFileInfoData->pStructMembers != NULL)
        {
            // Chained structures, like FILE_DIRECTORY_INFORMATION,
            // require different approach.
            if(pFileInfoData->bIsChain == FALSE)
            {
                nInputLength = FillStructureMembers(hTreeView,
                                                    hRootItem,
                                                    pFileInfoData->pStructMembers,
                                                    pData->pbFileInfoBuff);
            }
            else
            {
                nInputLength = FillVarLengthStructMembers(hTreeView, 
                                                            hRootItem,
                                                            pFileInfoData->pStructMembers,
                                                            pData->pbFileInfoBuff);
            }

            // Expand all subitems
            bShowTreeView = TRUE;
            bEnable = TRUE;
        }
    }

    // Enable/disable input length and setinfo button
    EnableDlgItems(hDlg, bEnable, IDC_INPUT_LENGTH_TITLE,
                                  IDC_INPUT_LENGTH,
                                  IDC_DEFAULT,
                                  0);

    // Enable/disable the "SetInfo" button
    if(bEnable)
        bEnable = IsHandleValid(pData->hFile);
    EnableDlgItems(hDlg, bEnable, IDC_QUERYINFO, IDC_QUERYDIR, IDC_SETINFO, 0);

    // Show/hide the tree view
    if(bShowTreeView != IsWindowVisible(hTreeView))
    {
        ShowWindow(hTreeView, bShowTreeView ? SW_SHOW : SW_HIDE);
        ShowWindow(hComment, bShowTreeView ? SW_HIDE : SW_SHOW);
    }

    return nInputLength;
}

static void EnableExitButton(HWND hDlg, BOOL bEnable)
{
    HWND hCancelButton = GetDlgItem(GetParent(hDlg), IDCANCEL);

    // Initialize the buttons
    // Hide "OK" button and change "Cancel" to "Exit"
    if(hCancelButton != NULL)
        EnableWindow(hCancelButton, bEnable);
    g_bDisableDialogDispatch = !bEnable;
}


static void UpdateDialog(HWND hDlg)
{
    TPropSheetData * pData = (TPropSheetData *)GetWindowLongPtr(hDlg, DWLP_USER);
    BOOL bEnable = FALSE;

    // Controls on the dialog will be enabled only if the
    // handle is valid and it is a NT handle

    if(IsHandleValid(pData->hFile))
        bEnable = TRUE;

    EnableDlgItems(hDlg, bEnable, IDC_QUERYINFO, IDC_QUERYDIR, IDC_SETINFO, 0);
}

//-----------------------------------------------------------------------------
// Message handlers

static int OnInitDialog(HWND hDlg, LPARAM lParam)
{
    FILE_INFORMATION_CLASS InitialFileInfo = FileBasicInformation;
    TPropSheetData * pData;
    PROPSHEETPAGE * pPage = (PROPSHEETPAGE *)lParam;
    HWND hCombo = GetDlgItem(hDlg, IDC_FILE_INFO_CLASS);
    int nInputLength;

    // Allocate the buffer for file information class.
    // Hopefully the struct size will never exceed 32 KB
    pData = (TPropSheetData *)pPage->lParam;
    ZeroMemory(pData->pbFileInfoBuff, pData->cbFileInfoBuff);

    // Initialize the dialog
    SetWindowLongPtr(hDlg, DWLP_USER, (LONG)pPage->lParam);

    // Fill the combo box with names of file information classes
    for(int i = 0; FileInfoData[i].szFileInfoClass != NULL; i++)
        ComboBox_AddString(hCombo, FileInfoData[i].szFileInfoClass);
    ComboBox_SetCurSel(hCombo, (int)InitialFileInfo - 1);

    // Initialize tree view with structure for current
    // file information class
    nInputLength = FillDialogWithFileInfo(hDlg, InitialFileInfo);
    SetDlgItemInt(hDlg, IDC_INPUT_LENGTH, nInputLength, FALSE);

    UpdateDialog(hDlg);
    return TRUE;
}

// Posted when the item label has been edited.
// We will fix the tree item to contain "Name: Value" text
static int OnReloadItems(HWND hDlg, HWND hTreeView, HTREEITEM hTreeItem)
{
    // If the treeview edit process has not been completed yet,
    // post the processing again
    if(TreeView_GetEditControl(hTreeView) != NULL)
    {
        PostMessage(hDlg, WM_RELOADITEMS, (WPARAM)hTreeView, (LPARAM)hTreeItem);
        return TRUE;
    }

    ReloadTreeViewItems(hDlg, hTreeView, hTreeItem);
    return TRUE;
}


static int OnSetActive(HWND hDlg)
{
    UpdateDialog(hDlg);
    return TRUE;
}

static int OnBeginLabelEdit(HWND hDlg, NMTVDISPINFO * pTVDispInfo)
{
    FILE_INFORMATION_CLASS FileInfoClass;

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?