NTFS alternate file stream editing
CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 9 of 9

Thread: NTFS alternate file stream editing

  1. #1
    Join Date
    Jul 2009
    Posts
    6

    NTFS alternate file stream editing

    Hey there I am trying to edit the NTFS metadata stream that contains "Author", "Keywords" ect. I need to mass edit these fields and I am wondering if there is a good tutorial to introduce me to working with streams in C++ and if the WinAPI is the right library for this.

  2. #2
    Join Date
    Nov 2003
    Location
    Belgium
    Posts
    8,062

    Re: NTFS alternate file stream editing

    This article explains streams from a programmers perspective and also this.

  3. #3
    Join Date
    Jul 2009
    Posts
    6

    Re: NTFS alternate file stream editing

    So far I have been able to make new file streams but I can't access the ones already set up for GUI editing like "Author"

    I do something like

    #include <cstdlib>
    #include <iostream>
    #include <fstream>
    #include <windows.h>

    using namespace std;
    int main(int argc, char *argv[])
    {
    ofstream myfile;
    myfile.open("test.txt:Keywords");
    myfile << "bah";
    myfile.close();
    }

    and it will make a new filestream called "Keywords" and write "bah" to it.

  4. #4
    Join Date
    Nov 2003
    Location
    Belgium
    Posts
    8,062

    Re: NTFS alternate file stream editing


  5. #5
    Join Date
    Aug 2006
    Location
    Longmont, Colorado
    Posts
    2

    Re: NTFS alternate file stream editing

    The Author, Keywords, Title, Comment, Date Taken and other meta data fields of image files (i.e. .jpg) are not written to an NTFS alternate stream. They are part of the metadata embedded in the default data stream.

    If you are using .Net and C#, here is a code snippet that will let you read the image metadata easily.

    I didn't actually compile this but you get the idea.

    Code:
            private void UpdateImage(string imageFile)
            {
                BitmapFrame bf = DecodeImage(imageFile);
                if (bf != null)
                {
                    BitmapMetadata bmd = (BitmapMetadata)bf.Metadata;
                    if (bmd != null && bmd.Keywords != null)
                    {
                        foreach (string keyword in bmd.Keywords)
                        {
                            MessageBox.Show(keyword, "Keywords");
                         }
                    }
                }
            }
    
            private BitmapFrame DecodeImage(string fileName)
            {
                Stream imageStream = null;
                string extension = string.Empty;
                BitmapFrame bitmapFrame = null;
                BitmapDecoder decoder = null;
    
                BitmapCreateOptions bco = BitmapCreateOptions.PreservePixelFormat;
    
                if (!string.IsNullOrEmpty(fileName) && File.Exists(fileName))
                {
                    try
                    {
                        Uri imageUri = new Uri(fileName, UriKind.Absolute);
                        using (imageStream = File.Open(fileName, FileMode.Open, FileAccess.Read, 
                            FileShare.Read))
                        {
                            extension = System.IO.Path.GetExtension(fileName);
                            switch (extension.ToLower())
                            {
                                case ".bmp":
                                    decoder = new BmpBitmapDecoder(imageUri, bco, 
                                        BitmapCacheOption.OnLoad);
                                    break;
                                case ".gif":
                                    decoder = new GifBitmapDecoder(imageUri, bco, 
                                        BitmapCacheOption.OnLoad);
                                    break;
                                case ".tif":
                                    decoder = new TiffBitmapDecoder(imageUri, bco, 
                                        BitmapCacheOption.OnLoad);
                                    break;
                                case ".jpg":
                                    decoder = new JpegBitmapDecoder(imageUri, 
                                        BitmapCreateOptions.IgnoreImageCache, BitmapCacheOption.OnLoad);
                                    break;
                                case ".png":
                                    decoder = new PngBitmapDecoder(imageUri, bco, 
                                        BitmapCacheOption.OnLoad);
                                    break;
                                case ".wdp":
                                    decoder = new WmpBitmapDecoder(imageUri, bco, 
                                        BitmapCacheOption.OnLoad);
                                    break;
                                default:
                                    break;
                            }
                            if (decoder != null)
                            {
                                bitmapFrame = decoder.Frames[0];
                            }
                            else
                            {
                                //
                                // if we can't get a decoder, Log message and try another image file...
                                //
                                MessageBox.Show(string.Format("  Unable to decode image file '{0}'", 
                                    fileName), "DecodeImage message");
                            }
                        }
                    }
                    catch (Exception excptn)
                    {
                        string msg = string.Format("File '{0}', {1}", fileName, excptn.Message);
                        MessageBox.Show(msg, "DecodeImage message", MessageBoxButton.OK, 
                            MessageBoxImage.Error);
                        if (imageStream != null)
                        {
                            imageStream.Close();
                            imageStream.Dispose();
                        }
                    }
                    if (bitmapFrame == null)
                    {
                        MessageBox.Show("Exiting DecodeImage() bitmapFrame: is null", "DecodeImage 
                            message");
                    }
                }
                else
                {
                    MessageBox.Show(string.Format("Image File {0} does not exist", 
                        fileName), "DecodeImage message");
                }
    
                return bitmapFrame;
            }
    If you want to update metadata, I put an code snippet, Write EXIF Metadata to Jpeg File, on Dream In Code under StCroixSkipper.

    If you want to play with NTFS Alternate Streams, I also posted a tutorial "Reading and Writing Alternate Streams in C# on Dream In Code, also under StCroixSkipper.
    Last edited by Marc G; August 6th, 2009 at 03:56 AM. Reason: Added code tags

  6. #6
    Join Date
    Jul 2009
    Posts
    6

    Re: NTFS alternate file stream editing

    Quote Originally Posted by Marc G View Post
    Thanks man! I was totally going in the wrong direction there. This makes much more sense now! Although editing the SummaryInformation stream doesn't seem fun. I'm going to give it a try anyways.

    Thanks jsmoreland. I haven't ever used anything of VB except some basic GUI based version in High school a few years ago. I'm currently picked up the syntax of C++ off of knowing Java. Is it much of a difference between C# and C++?

  7. #7
    Join Date
    Jul 2009
    Posts
    6

    Re: NTFS alternate file stream editing

    So I was poking around the MSDN and found this http://msdn.microsoft.com/en-us/libr...56(VS.85).aspx

    I believe this will let me set and edit the SummaryInformation stream but it mentions something about needing to send the information in the get method to a database for windows installer. Anyone done anything like this before?

  8. #8
    Join Date
    Aug 2006
    Location
    Longmont, Colorado
    Posts
    2

    Re: NTFS alternate file stream editing

    C# and Java share much the same syntax. C# is much more straight forward than C++.
    C++ has many complications because of its origin, such as multiple inheritance, passing by value and passing by reference. Basically, C++, although I've used it for many years, is a more complicated language than C#.

    The only problem I see is many of the Win32 api's aren't available directly from C#. But it is fairly easy to build the pieces you need to call all of the Win32 api's from C#. Checkout PInvoke.com.

  9. #9
    Join Date
    Jul 2009
    Posts
    6

    Re: NTFS alternate file stream editing

    My room mate's favorite language is C#. I heard that you can also write in C++ and C code into C# programs these days. That is the direction I am moving in eventually.

    I talked to some people on IRC and there seems to be a problem where if I go to update the SI stream using something like MsiSummaryInfoGetPropertyCount() it will only update the SI database and not the file itself which leads to the problem of the next indexing run overwriting the cache in the FS. I am re-thinking using ADS's to put in the information but that seems a little pointless since the objective is to have the end users see the information in order to check it if they must.

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  


Windows Mobile Development Center


Click Here to Expand Forum to Full Width

This is a CodeGuru survey question.


Featured


HTML5 Development Center