Example #1
0
        private static PROPSPEC GetPROPSEC(CompoundProperty prop)
        {
            var spec = new PROPSPEC();

            if (prop.IsKnownProperty)
            {
                spec.ulKind       = PRSPEC.PRSPEC_PROPID;
                spec.union.propid = prop.Id;
            }
            else
            {
                spec.ulKind       = PRSPEC.PRSPEC_LPWSTR;
                spec.union.lpwstr = Marshal.StringToCoTaskMemUni(prop.Name);
            }
            return(spec);
        }
Example #2
0
 private static string GetPropertyValue(IWiaPropertyStorage propertyStorage, uint propid)
 {
     PROPVARIANT[] propvars = new PROPVARIANT[1];
     PROPSPEC[]    propspec = new PROPSPEC[1];
     propspec[0].ulKind   = (uint)1;//PRSPEC.PROPID;
     propspec[0].u.propId = propid;
     try
     {
         if (Success(propertyStorage.ReadMultiple(1, propspec, propvars)))
         {
             return(propvars[0].Value.ToString());
         }
     }
     finally
     {
         propvars[0].Clear();
     }
     return(null);
 }
Example #3
0
        /// <summary>
        /// Commits the changes if any.
        /// </summary>
        /// <returns>true if changes were detected and commited; otherwise false.</returns>
        public bool CommitChanges()
        {
            // group properties by property set (fmtid)
            var sets = new Dictionary <Guid, List <CompoundProperty> >();

            foreach (var property in TouchedProperties)
            {
                if (!sets.TryGetValue(property.FormatId, out var list))
                {
                    list = new List <CompoundProperty>();
                    sets.Add(property.FormatId, list);
                }

                list.Add(property);
            }

            if (sets.Count == 0)
            {
                return(false);
            }

            var mode = GetMode(readOnly: false);

            var guid = typeof(IPropertySetStorage).GUID;
            var hr   = StgOpenStorageEx(FilePath, mode, STGFMT.STGFMT_ANY, 0, IntPtr.Zero, IntPtr.Zero, ref guid, out var propertySetStorage);

            if (hr == STG_E_FILENOTFOUND || hr == STG_E_PATHNOTFOUND)
            {
                throw new FileNotFoundException(null, FilePath);
            }

            if (hr != 0)
            {
                throw new Win32Exception((int)hr);
            }

            try
            {
                foreach (var kvp in sets)
                {
                    var        fmtid = kvp.Key;
                    const STGM Mode2 = STGM.STGM_READWRITE | STGM.STGM_SHARE_EXCLUSIVE;
                    hr = propertySetStorage.Open(ref fmtid, Mode2, out var propertyStorage);
                    if (hr == STG_E_FILENOTFOUND)
                    {
                        if (OnlyDeletes(kvp.Value))
                        {
                            continue;
                        }

                        var nullGuid = Guid.Empty;
                        hr = propertySetStorage.Create(ref fmtid, ref nullGuid, PROPSETFLAG_ANSI, Mode2, out propertyStorage);
                    }

                    if (hr != 0)
                    {
                        throw new Win32Exception((int)hr);
                    }

                    try
                    {
                        foreach (var property in kvp.Value)
                        {
                            if (property.Deleted)
                            {
                                var specs = new PROPSPEC[]
                                {
                                    GetPROPSEC(property),
                                };

                                try
                                {
                                    hr = propertyStorage.DeleteMultiple(1, specs);
                                    if (hr != 0)
                                    {
                                        throw new Win32Exception((int)hr);
                                    }
                                }
                                finally
                                {
                                    FreePROPSEC(ref specs[0]);
                                }
                            }
                        }

                        foreach (var property in kvp.Value)
                        {
                            if (property.Changed)
                            {
                                var specs = new PROPSPEC[]
                                {
                                    GetPROPSEC(property),
                                };

                                var vars = new PROPVARIANT[]
                                {
                                    GetPROPVARIANT(property),
                                };

                                try
                                {
                                    hr = propertyStorage.WriteMultiple(1, specs, vars, USERDEFINEDPROPERTIES_MIN);
                                    if (hr != 0)
                                    {
                                        throw new Win32Exception((int)hr);
                                    }
                                }
                                finally
                                {
                                    FreePROPSEC(ref specs[0]);
                                    PropVariantClear(ref vars[0]);
                                }
                            }
                        }

                        propertyStorage.Commit(0);
                    }
                    finally
                    {
                        Marshal.ReleaseComObject(propertyStorage);
                    }
                }
            }
            finally
            {
                if (propertySetStorage != null)
                {
                    Marshal.ReleaseComObject(propertySetStorage);
                }
            }

            Properties.Commit();
            return(true);
        }
Example #4
0
 private static void FreePROPSEC(ref PROPSPEC spec)
 {
     Marshal.FreeCoTaskMem(spec.union.lpwstr);
     spec.union.lpwstr = IntPtr.Zero;
 }
Example #5
0
        private void LoadPropertySet(IPropertySetStorage propertySetStorage, Guid fmtid)
        {
            var guid = fmtid;
            var hr   = propertySetStorage.Open(ref guid, STGM.STGM_READ | STGM.STGM_SHARE_EXCLUSIVE, out var propertyStorage);

            if (hr == STG_E_FILENOTFOUND || hr == STG_E_ACCESSDENIED)
            {
                return;
            }

            if (hr != 0)
            {
                throw new Win32Exception((int)hr);
            }

            propertyStorage.Enum(out var es);
            if (es == null)
            {
                return;
            }

            try
            {
                var stg = new STATPROPSTG();
                int fetched;
                do
                {
                    hr = es.Next(1, ref stg, out fetched);
                    if (hr != 0 && hr != 1)
                    {
                        throw new Win32Exception((int)hr);
                    }

                    if (fetched == 1)
                    {
                        var name = GetPropertyName(fmtid, propertyStorage, stg);

                        var propsec = new PROPSPEC[]
                        {
                            new PROPSPEC
                            {
                                ulKind = stg.lpwstrName != null ? PRSPEC.PRSPEC_LPWSTR : PRSPEC.PRSPEC_PROPID,
                            },
                        };

                        var lpwstr = IntPtr.Zero;
                        if (stg.lpwstrName != null)
                        {
                            lpwstr = Marshal.StringToCoTaskMemUni(stg.lpwstrName);
                            propsec[0].union.lpwstr = lpwstr;
                        }
                        else
                        {
                            propsec[0].union.propid = stg.propid;
                        }

                        var vars = new PROPVARIANT[1];
                        vars[0] = new PROPVARIANT();
                        try
                        {
                            hr = propertyStorage.ReadMultiple(1, propsec, vars);
                            if (hr != 0)
                            {
                                throw new Win32Exception((int)hr);
                            }
                        }
                        finally
                        {
                            if (lpwstr != IntPtr.Zero)
                            {
                                Marshal.FreeCoTaskMem(lpwstr);
                            }
                        }

                        object value;
                        try
                        {
                            switch (vars[0].vt)
                            {
                            case VARTYPE.VT_BOOL:
                                value = vars[0].union.boolVal != 0 ? true : false;
                                break;

                            case VARTYPE.VT_BSTR:
                                value = Marshal.PtrToStringUni(vars[0].union.bstrVal);
                                break;

                            case VARTYPE.VT_CY:
                                value = decimal.FromOACurrency(vars[0].union.cyVal);
                                break;

                            case VARTYPE.VT_DATE:
                                value = DateTime.FromOADate(vars[0].union.date);
                                break;

                            case VARTYPE.VT_DECIMAL:
                                var dec = IntPtr.Zero;
                                Marshal.StructureToPtr(vars[0], dec, false);
                                value = Marshal.PtrToStructure(dec, typeof(decimal));
                                break;

                            case VARTYPE.VT_DISPATCH:
                                value = Marshal.GetObjectForIUnknown(vars[0].union.pdispVal);
                                break;

                            case VARTYPE.VT_ERROR:
                            case VARTYPE.VT_HRESULT:
                                value = vars[0].union.scode;
                                break;

                            case VARTYPE.VT_FILETIME:
                                value = DateTime.FromFileTime(vars[0].union.filetime);
                                break;

                            case VARTYPE.VT_I1:
                                value = vars[0].union.cVal;
                                break;

                            case VARTYPE.VT_I2:
                                value = vars[0].union.iVal;
                                break;

                            case VARTYPE.VT_I4:
                                value = vars[0].union.lVal;
                                break;

                            case VARTYPE.VT_I8:
                                value = vars[0].union.hVal;
                                break;

                            case VARTYPE.VT_INT:
                                value = vars[0].union.intVal;
                                break;

                            case VARTYPE.VT_LPSTR:
                                value = Marshal.PtrToStringAnsi(vars[0].union.pszVal);
                                break;

                            case VARTYPE.VT_LPWSTR:
                                value = Marshal.PtrToStringUni(vars[0].union.pwszVal);
                                break;

                            case VARTYPE.VT_R4:
                                value = vars[0].union.fltVal;
                                break;

                            case VARTYPE.VT_R8:
                                value = vars[0].union.dblVal;
                                break;

                            case VARTYPE.VT_UI1:
                                value = vars[0].union.bVal;
                                break;

                            case VARTYPE.VT_UI2:
                                value = vars[0].union.uiVal;
                                break;

                            case VARTYPE.VT_UI4:
                                value = vars[0].union.ulVal;
                                break;

                            case VARTYPE.VT_UI8:
                                value = vars[0].union.uhVal;
                                break;

                            case VARTYPE.VT_UINT:
                                value = vars[0].union.uintVal;
                                break;

                            case VARTYPE.VT_UNKNOWN:
                                value = Marshal.GetObjectForIUnknown(vars[0].union.punkVal);
                                break;

                            default:
                                value = null;
                                break;
                            }
                        }
                        finally
                        {
                            PropVariantClear(ref vars[0]);
                        }

                        var property = new CompoundProperty(fmtid, name, stg.propid)
                        {
                            Value   = value,
                            Changed = false,
                        };
                        Properties.InternalAdd(property);
                    }
                }while (fetched == 1);
            }
            finally
            {
                Marshal.ReleaseComObject(es);
            }
        }
Example #6
0
            void IPropertyStorage.DeleteMultiple(
                UInt32 cpspec,
                PROPSPEC[] rgpspec
                )
            {
                SecurityHelper.DemandCompoundFileIOPermission();

                _unsafePropertyStorage.DeleteMultiple(
                    cpspec,
                    rgpspec
                    );
            }
Example #7
0
            void IPropertyStorage.WriteMultiple(
                UInt32 cpspec,
                PROPSPEC[] rgpspec,
                PROPVARIANT[] rgpropvar,
                uint propidNameFirst
                )
            {
                SecurityHelper.DemandCompoundFileIOPermission();

                _unsafePropertyStorage.WriteMultiple(
                    cpspec,
                    rgpspec,
                    rgpropvar,
                    propidNameFirst
                    );
            }
Example #8
0
            //
            // We preserve the HRESULT on this method because we need to distinguish
            // between S_OK (we got the properties we asked for) and S_FALSE (none of
            // the properties exist).
            //
            int IPropertyStorage.ReadMultiple(
                UInt32 cpspec,
                PROPSPEC[] rgpspec,
                PROPVARIANT[] rgpropvar
                )
            {
                SecurityHelper.DemandCompoundFileIOPermission();

                return _unsafePropertyStorage.ReadMultiple(
                    cpspec,
                    rgpspec,
                    rgpropvar
                    );
            }
Example #9
0
        private static DocumentPropertyCollection ReadFromStructuredStorage(string path)
        {
            var result = NativeMethods.StgOpenStorage(path, null, STGM.READ | STGM.SHARE_DENY_WRITE, IntPtr.Zero, 0, out var storage);

            if (result != 0)
            {
                var e = Marshal.GetExceptionForHR(result);
                throw e;
            }

            var propertySetStorage = storage as IPropertySetStorage;
            var properties         = new DocumentPropertyCollection();

            foreach (var statPropSetStg in propertySetStorage.AsEnumerable())
            {
                var fmtid = statPropSetStg.fmtid;
                propertySetStorage.Open(ref fmtid, (uint)(STGM.READ | STGM.SHARE_EXCLUSIVE), out var propertyStorage);

                foreach (var statPropStg in propertyStorage.AsEnumerable())
                {
                    var        propSpecArray = new PROPSPEC[1];
                    const uint PRSPEC_PROPID = 1;
                    propSpecArray[0].ulKind      = PRSPEC_PROPID;
                    propSpecArray[0].unionmember = new IntPtr(statPropStg.PROPID);
                    var propVariantArray = new PropVariant[1];
                    propertyStorage.ReadMultiple(1, propSpecArray, propVariantArray);
                    var propVariant = propVariantArray[0];

                    try
                    {
                        var value = propVariant.Value;

                        DocumentPropertyId id;
                        if (statPropSetStg.fmtid == PropertySetId.Summary)
                        {
                            switch ((StgSummaryPropertyId)statPropStg.PROPID)
                            {
                            case StgSummaryPropertyId.Author:
                                id = DocumentPropertyId.Creator;
                                break;

                            case StgSummaryPropertyId.CharCount:
                                id = DocumentPropertyId.Characters;
                                break;

                            case StgSummaryPropertyId.Comments:
                                id = DocumentPropertyId.Description;
                                break;

                            case StgSummaryPropertyId.CreateDate:
                                id = DocumentPropertyId.Created;
                                break;

                            case StgSummaryPropertyId.CreatingApplicationName:
                                id = DocumentPropertyId.Application;
                                break;

                            case StgSummaryPropertyId.Keywords:
                                id = DocumentPropertyId.Keywords;
                                break;

                            case StgSummaryPropertyId.LastAuthor:
                                id = DocumentPropertyId.LastModifiedBy;
                                break;

                            case StgSummaryPropertyId.LastPrinted:
                                id = DocumentPropertyId.LastPrinted;
                                break;

                            case StgSummaryPropertyId.LastSaveDate:
                                id = DocumentPropertyId.Modified;
                                break;

                            case StgSummaryPropertyId.PageCount:
                                id = DocumentPropertyId.Pages;
                                break;

                            case StgSummaryPropertyId.RevisionNumber:
                                id = DocumentPropertyId.Revision;
                                break;

                            case StgSummaryPropertyId.Security:
                                id = DocumentPropertyId.DocSecurity;
                                break;

                            case StgSummaryPropertyId.Subject:
                                id = DocumentPropertyId.Subject;
                                break;

                            case StgSummaryPropertyId.Template:
                                id = DocumentPropertyId.Template;
                                break;

                            case StgSummaryPropertyId.Title:
                                id = DocumentPropertyId.Title;
                                break;

                            case StgSummaryPropertyId.TotalEditingTime:
                                id = DocumentPropertyId.TotalTime;
                                var dateTime = (DateTime)value;
                                var timeSpan = dateTime - DateTime.FromFileTimeUtc(0);
                                value = timeSpan;
                                break;

                            case StgSummaryPropertyId.WordCount:
                                id = DocumentPropertyId.Words;
                                break;

                            default:
                                throw new NotImplementedException();
                            }
                        }
                        else if (statPropSetStg.fmtid == PropertySetId.DocumentSummary)
                        {
                            id = DocumentPropertyId.None;

                            switch ((StgDocumentSummaryPropertyId)statPropStg.PROPID)
                            {
                            case StgDocumentSummaryPropertyId.ByteCount:
                                break;

                            case StgDocumentSummaryPropertyId.Category:
                                id = DocumentPropertyId.Category;
                                break;

                            case StgDocumentSummaryPropertyId.Company:
                                id = DocumentPropertyId.Company;
                                break;

                            case StgDocumentSummaryPropertyId.HeadingPairs:
                                break;

                            case StgDocumentSummaryPropertyId.HiddenSlideCount:
                                break;

                            case StgDocumentSummaryPropertyId.LineCount:
                                id = DocumentPropertyId.Lines;
                                break;

                            case StgDocumentSummaryPropertyId.LinksUpToDate:
                                id = DocumentPropertyId.LinksUpToDate;
                                break;

                            case StgDocumentSummaryPropertyId.Manager:
                                id = DocumentPropertyId.Manager;
                                break;

                            case StgDocumentSummaryPropertyId.MMClipCount:
                                break;

                            case StgDocumentSummaryPropertyId.NoteCount:
                                break;

                            case StgDocumentSummaryPropertyId.ParagraphCount:
                                id = DocumentPropertyId.Paragraphs;
                                break;

                            case StgDocumentSummaryPropertyId.PresentationTarget:
                                break;

                            case StgDocumentSummaryPropertyId.ScaleCrop:
                                id = DocumentPropertyId.ScaleCrop;
                                break;

                            case StgDocumentSummaryPropertyId.SlideCount:
                                break;

                            case StgDocumentSummaryPropertyId.TitlesofParts:
                                break;

                            default:
                                break;
                            }
                        }
                        else
                        {
                            throw new NotImplementedException();
                        }

                        if (id != DocumentPropertyId.None)
                        {
                            properties.Add(id, value);
                        }
                    }
                    catch
                    {
                    }
                }
            }

            return(properties);
        }