|  | /******************************************************************************* | 
|  | * You may amend and distribute as you like, but don't remove this header! | 
|  | * | 
|  | * EPPlus provides server-side generation of Excel 2007/2010 spreadsheets. | 
|  | * See http://www.codeplex.com/EPPlus for details. | 
|  | * | 
|  | * Copyright (C) 2011  Jan Källman | 
|  | * | 
|  | * All code and executables are provided "as is" with no warranty either express or implied. | 
|  | * The author accepts no liability for any damage or loss of business that this product may cause. | 
|  | * | 
|  | * If you want to understand this code have a look at the Office VBA File Format Structure Specification (MS-OVBA.PDF) or | 
|  | * http://msdn.microsoft.com/en-us/library/cc313094(v=office.12).aspx | 
|  | * | 
|  | * * Code change notes: | 
|  | * | 
|  | * Author							Change						Date | 
|  | ******************************************************************************* | 
|  | * Jan Källman		Added		26-MAR-2012 | 
|  | *******************************************************************************/ | 
|  | using System; | 
|  | using System.Collections.Generic; | 
|  | using System.Globalization; | 
|  | using System.Linq; | 
|  | using System.Text; | 
|  | using System.IO; | 
|  | using OfficeOpenXml.Utils; | 
|  | using System.Security.Cryptography.Pkcs; | 
|  | using System.Security.Cryptography.X509Certificates; | 
|  | using System.Security.Cryptography; | 
|  | using System.Text.RegularExpressions; | 
|  |  | 
|  | namespace OfficeOpenXml.VBA | 
|  | { | 
|  | /// <summary> | 
|  | /// Represents the VBA project part of the package | 
|  | /// </summary> | 
|  | public class ExcelVbaProject | 
|  | { | 
|  | const string schemaRelVba = "http://schemas.microsoft.com/office/2006/relationships/vbaProject"; | 
|  | internal const string PartUri = @"/xl/vbaProject.bin"; | 
|  | #region Classes & Enums | 
|  | /// <summary> | 
|  | /// Type of system where the VBA project was created. | 
|  | /// </summary> | 
|  | public enum eSyskind | 
|  | { | 
|  | Win16 = 0, | 
|  | Win32 = 1, | 
|  | Macintosh = 2, | 
|  | Win64 = 3 | 
|  | } | 
|  |  | 
|  | #endregion | 
|  | internal ExcelVbaProject(ExcelWorkbook wb) | 
|  | { | 
|  | _wb = wb; | 
|  | _pck = _wb._package.Package; | 
|  | References = new ExcelVbaReferenceCollection(); | 
|  | Modules = new ExcelVbaModuleCollection(this); | 
|  | var rel = _wb.Part.GetRelationshipsByType(schemaRelVba).FirstOrDefault(); | 
|  | if (rel != null) | 
|  | { | 
|  | Uri = UriHelper.ResolvePartUri(rel.SourceUri, rel.TargetUri); | 
|  | Part = _pck.GetPart(Uri); | 
|  | #if !MONO | 
|  | GetProject(); | 
|  | #endif | 
|  | } | 
|  | else | 
|  | { | 
|  | Lcid = 0; | 
|  | Part = null; | 
|  | } | 
|  | } | 
|  | internal ExcelWorkbook _wb; | 
|  | internal Packaging.ZipPackage _pck; | 
|  | #region Dir Stream Properties | 
|  | /// <summary> | 
|  | /// System kind. Default Win32. | 
|  | /// </summary> | 
|  | public eSyskind SystemKind { get; set; } | 
|  | /// <summary> | 
|  | /// Name of the project | 
|  | /// </summary> | 
|  | public string Name { get; set; } | 
|  | /// <summary> | 
|  | /// A description of the project | 
|  | /// </summary> | 
|  | public string Description { get; set; } | 
|  | /// <summary> | 
|  | /// A helpfile | 
|  | /// </summary> | 
|  | public string HelpFile1 { get; set; } | 
|  | /// <summary> | 
|  | /// Secondary helpfile | 
|  | /// </summary> | 
|  | public string HelpFile2 { get; set; } | 
|  | /// <summary> | 
|  | /// Context if refering the helpfile | 
|  | /// </summary> | 
|  | public int HelpContextID { get; set; } | 
|  | /// <summary> | 
|  | /// Conditional compilation constants | 
|  | /// </summary> | 
|  | public string Constants { get; set; } | 
|  | /// <summary> | 
|  | /// Codepage for encoding. Default is current regional setting. | 
|  | /// </summary> | 
|  | public int CodePage { get; internal set; } | 
|  | internal int LibFlags { get; set; } | 
|  | internal int MajorVersion { get; set; } | 
|  | internal int MinorVersion { get; set; } | 
|  | internal int Lcid { get; set; } | 
|  | internal int LcidInvoke { get; set; } | 
|  | internal string ProjectID { get; set; } | 
|  | internal string ProjectStreamText { get; set; } | 
|  | /// <summary> | 
|  | /// Project references | 
|  | /// </summary> | 
|  | public ExcelVbaReferenceCollection References { get; set; } | 
|  | /// <summary> | 
|  | /// Code Modules (Modules, classes, designer code) | 
|  | /// </summary> | 
|  | public ExcelVbaModuleCollection Modules { get; set; } | 
|  | ExcelVbaSignature _signature = null; | 
|  | /// <summary> | 
|  | /// The digital signature | 
|  | /// </summary> | 
|  | public ExcelVbaSignature Signature | 
|  | { | 
|  | get | 
|  | { | 
|  | if (_signature == null) | 
|  | { | 
|  | _signature=new ExcelVbaSignature(Part); | 
|  | } | 
|  | return _signature; | 
|  | } | 
|  | } | 
|  | ExcelVbaProtection _protection=null; | 
|  | /// <summary> | 
|  | /// VBA protection | 
|  | /// </summary> | 
|  | public ExcelVbaProtection Protection | 
|  | { | 
|  | get | 
|  | { | 
|  | if (_protection == null) | 
|  | { | 
|  | _protection = new ExcelVbaProtection(this); | 
|  | } | 
|  | return _protection; | 
|  | } | 
|  | } | 
|  | #endregion | 
|  | #if !MONO | 
|  | #region Read Project | 
|  | private void GetProject() | 
|  | { | 
|  |  | 
|  | var stream = Part.GetStream(); | 
|  | byte[] vba; | 
|  | vba = new byte[stream.Length]; | 
|  | stream.Read(vba, 0, (int)stream.Length); | 
|  | Document = new CompoundDocument(vba); | 
|  |  | 
|  | ReadDirStream(); | 
|  | ProjectStreamText = Encoding.GetEncoding(CodePage).GetString(Document.Storage.DataStreams["PROJECT"]); | 
|  | ReadModules(); | 
|  | ReadProjectProperties(); | 
|  | } | 
|  | private void ReadModules() | 
|  | { | 
|  | foreach (var modul in Modules) | 
|  | { | 
|  | var stream = Document.Storage.SubStorage["VBA"].DataStreams[modul.streamName]; | 
|  | var byCode = CompoundDocument.DecompressPart(stream, (int)modul.ModuleOffset); | 
|  | string code = Encoding.GetEncoding(CodePage).GetString(byCode); | 
|  | int pos=0; | 
|  | while(pos+9<code.Length && code.Substring(pos,9)=="Attribute") | 
|  | { | 
|  | int linePos=code.IndexOf("\r\n",pos); | 
|  | string[] lineSplit; | 
|  | if(linePos>0) | 
|  | { | 
|  | lineSplit = code.Substring(pos + 9, linePos - pos - 9).Split('='); | 
|  | } | 
|  | else | 
|  | { | 
|  | lineSplit=code.Substring(pos+9).Split(new char[]{'='},1); | 
|  | } | 
|  | if (lineSplit.Length > 1) | 
|  | { | 
|  | lineSplit[1] = lineSplit[1].Trim(); | 
|  | var attr = | 
|  | new ExcelVbaModuleAttribute() | 
|  | { | 
|  | Name = lineSplit[0].Trim(), | 
|  | DataType = lineSplit[1].StartsWith("\"") ? eAttributeDataType.String : eAttributeDataType.NonString, | 
|  | Value = lineSplit[1].StartsWith("\"") ? lineSplit[1].Substring(1, lineSplit[1].Length - 2) : lineSplit[1] | 
|  | }; | 
|  | modul.Attributes._list.Add(attr); | 
|  | } | 
|  | pos = linePos + 2; | 
|  | } | 
|  | modul.Code=code.Substring(pos); | 
|  | } | 
|  | } | 
|  |  | 
|  | private void ReadProjectProperties() | 
|  | { | 
|  | _protection = new ExcelVbaProtection(this); | 
|  | string prevPackage = ""; | 
|  | var lines = Regex.Split(ProjectStreamText, "\r\n"); | 
|  | foreach (string line in lines) | 
|  | { | 
|  | if (line.StartsWith("[")) | 
|  | { | 
|  |  | 
|  | } | 
|  | else | 
|  | { | 
|  | var split = line.Split('='); | 
|  | if (split.Length > 1 && split[1].Length > 1 && split[1].StartsWith("\"")) //Remove any double qouates | 
|  | { | 
|  | split[1] = split[1].Substring(1, split[1].Length - 2); | 
|  | } | 
|  | switch (split[0]) | 
|  | { | 
|  | case "ID": | 
|  | ProjectID = split[1]; | 
|  | break; | 
|  | case "Document": | 
|  | string mn = split[1].Substring(0, split[1].IndexOf("/&H")); | 
|  | Modules[mn].Type = eModuleType.Document; | 
|  | break; | 
|  | case "Package": | 
|  | prevPackage = split[1]; | 
|  | break; | 
|  | case "BaseClass": | 
|  | Modules[split[1]].Type = eModuleType.Designer; | 
|  | Modules[split[1]].ClassID = prevPackage; | 
|  | break; | 
|  | case "Module": | 
|  | Modules[split[1]].Type = eModuleType.Module; | 
|  | break; | 
|  | case "Class": | 
|  | Modules[split[1]].Type = eModuleType.Class; | 
|  | break; | 
|  | case "HelpFile": | 
|  | case "Name": | 
|  | case "HelpContextID": | 
|  | case "Description": | 
|  | case "VersionCompatible32": | 
|  | break; | 
|  | //393222000" | 
|  | case "CMG": | 
|  | byte[] cmg = Decrypt(split[1]); | 
|  | _protection.UserProtected = (cmg[0] & 1) != 0; | 
|  | _protection.HostProtected = (cmg[0] & 2) != 0; | 
|  | _protection.VbeProtected = (cmg[0] & 4) != 0; | 
|  | break; | 
|  | case "DPB": | 
|  | byte[] dpb = Decrypt(split[1]); | 
|  | if (dpb.Length >= 28) | 
|  | { | 
|  | byte reserved = dpb[0]; | 
|  | var flags = new byte[3]; | 
|  | Array.Copy(dpb, 1, flags, 0, 3); | 
|  | var keyNoNulls = new byte[4]; | 
|  | _protection.PasswordKey = new byte[4]; | 
|  | Array.Copy(dpb, 4, keyNoNulls, 0, 4); | 
|  | var hashNoNulls = new byte[20]; | 
|  | _protection.PasswordHash = new byte[20]; | 
|  | Array.Copy(dpb, 8, hashNoNulls, 0, 20); | 
|  | //Handle 0x00 bitwise 2.4.4.3 | 
|  | for (int i = 0; i < 24; i++) | 
|  | { | 
|  | int bit = 128 >> (int)((i % 8)); | 
|  | if (i < 4) | 
|  | { | 
|  | if ((int)(flags[0] & bit) == 0) | 
|  | { | 
|  | _protection.PasswordKey[i] = 0; | 
|  | } | 
|  | else | 
|  | { | 
|  | _protection.PasswordKey[i] = keyNoNulls[i]; | 
|  | } | 
|  | } | 
|  | else | 
|  | { | 
|  | int flagIndex = (i - i % 8) / 8; | 
|  | if ((int)(flags[flagIndex] & bit) == 0) | 
|  | { | 
|  | _protection.PasswordHash[i - 4] = 0; | 
|  | } | 
|  | else | 
|  | { | 
|  | _protection.PasswordHash[i - 4] = hashNoNulls[i - 4]; | 
|  | } | 
|  | } | 
|  | } | 
|  | } | 
|  | break; | 
|  | case "GC": | 
|  | _protection.VisibilityState = Decrypt(split[1])[0] == 0xFF; | 
|  |  | 
|  | break; | 
|  | } | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | /// <summary> | 
|  | /// 2.4.3.3 Decryption | 
|  | /// </summary> | 
|  | /// <param name="value">Byte hex string</param> | 
|  | /// <returns>The decrypted value</returns> | 
|  | private byte[] Decrypt(string value) | 
|  | { | 
|  | byte[] enc = GetByte(value); | 
|  | byte[] dec = new byte[(value.Length - 1)]; | 
|  | byte seed, version, projKey, ignoredLength; | 
|  | seed = enc[0]; | 
|  | dec[0] = (byte)(enc[1] ^ seed); | 
|  | dec[1] = (byte)(enc[2] ^ seed); | 
|  | for (int i = 2; i < enc.Length - 1; i++) | 
|  | { | 
|  | dec[i] = (byte)(enc[i + 1] ^ (enc[i - 1] + dec[i - 1])); | 
|  | } | 
|  | version = dec[0]; | 
|  | projKey = dec[1]; | 
|  | ignoredLength = (byte)((seed & 6) / 2); | 
|  | int datalength = BitConverter.ToInt32(dec, ignoredLength + 2); | 
|  | var data = new byte[datalength]; | 
|  | Array.Copy(dec, 6 + ignoredLength, data, 0, datalength); | 
|  | return data; | 
|  | } | 
|  | /// <summary> | 
|  | /// 2.4.3.2 Encryption | 
|  | /// </summary> | 
|  | /// <param name="value"></param> | 
|  | /// <returns>Byte hex string</returns> | 
|  | private string Encrypt(byte[] value) | 
|  | { | 
|  | byte[] seed = new byte[1]; | 
|  | var rn = RandomNumberGenerator.Create(); | 
|  | rn.GetBytes(seed); | 
|  | BinaryWriter br = new BinaryWriter(new MemoryStream()); | 
|  | byte[] enc = new byte[value.Length + 10]; | 
|  | enc[0] = seed[0]; | 
|  | enc[1] = (byte)(2 ^ seed[0]); | 
|  |  | 
|  | byte projKey = 0; | 
|  |  | 
|  | foreach (var c in ProjectID) | 
|  | { | 
|  | projKey += (byte)c; | 
|  | } | 
|  | enc[2] = (byte)(projKey ^ seed[0]); | 
|  | var ignoredLength = (seed[0] & 6) / 2; | 
|  | for (int i = 0; i < ignoredLength; i++) | 
|  | { | 
|  | br.Write(seed[0]); | 
|  | } | 
|  | br.Write(value.Length); | 
|  | br.Write(value); | 
|  |  | 
|  | int pos = 3; | 
|  | byte pb = projKey; | 
|  | foreach (var b in ((MemoryStream)br.BaseStream).ToArray()) | 
|  | { | 
|  | enc[pos] = (byte)(b ^ (enc[pos - 2] + pb)); | 
|  | pos++; | 
|  | pb = b; | 
|  | } | 
|  |  | 
|  | return GetString(enc, pos - 1); | 
|  | } | 
|  | private string GetString(byte[] value, int max) | 
|  | { | 
|  | string ret = ""; | 
|  | for (int i = 0; i <= max; i++) | 
|  | { | 
|  | if (value[i] < 16) | 
|  | { | 
|  | ret += "0" + value[i].ToString("x"); | 
|  | } | 
|  | else | 
|  | { | 
|  | ret += value[i].ToString("x"); | 
|  | } | 
|  | } | 
|  | return ret.ToUpper(CultureInfo.InvariantCulture); | 
|  | } | 
|  | private byte[] GetByte(string value) | 
|  | { | 
|  | byte[] ret = new byte[value.Length / 2]; | 
|  | for (int i = 0; i < ret.Length; i++) | 
|  | { | 
|  | ret[i] = byte.Parse(value.Substring(i * 2, 2), System.Globalization.NumberStyles.AllowHexSpecifier); | 
|  | } | 
|  | return ret; | 
|  | } | 
|  | private void ReadDirStream() | 
|  | { | 
|  | byte[] dir = CompoundDocument.DecompressPart(Document.Storage.SubStorage["VBA"].DataStreams["dir"]); | 
|  | MemoryStream ms = new MemoryStream(dir); | 
|  | BinaryReader br = new BinaryReader(ms); | 
|  | ExcelVbaReference currentRef = null; | 
|  | string referenceName = ""; | 
|  | ExcelVBAModule currentModule = null; | 
|  | bool terminate = false; | 
|  | while (br.BaseStream.Position < br.BaseStream.Length && terminate == false) | 
|  | { | 
|  | ushort id = br.ReadUInt16(); | 
|  | uint size = br.ReadUInt32(); | 
|  | switch (id) | 
|  | { | 
|  | case 0x01: | 
|  | SystemKind = (eSyskind)br.ReadUInt32(); | 
|  | break; | 
|  | case 0x02: | 
|  | Lcid = (int)br.ReadUInt32(); | 
|  | break; | 
|  | case 0x03: | 
|  | CodePage = (int)br.ReadUInt16(); | 
|  | break; | 
|  | case 0x04: | 
|  | Name = GetString(br, size); | 
|  | break; | 
|  | case 0x05: | 
|  | Description = GetUnicodeString(br, size); | 
|  | break; | 
|  | case 0x06: | 
|  | HelpFile1 = GetString(br, size); | 
|  | break; | 
|  | case 0x3D: | 
|  | HelpFile2 = GetString(br, size); | 
|  | break; | 
|  | case 0x07: | 
|  | HelpContextID = (int)br.ReadUInt32(); | 
|  | break; | 
|  | case 0x08: | 
|  | LibFlags = (int)br.ReadUInt32(); | 
|  | break; | 
|  | case 0x09: | 
|  | MajorVersion = (int)br.ReadUInt32(); | 
|  | MinorVersion = (int)br.ReadUInt16(); | 
|  | break; | 
|  | case 0x0C: | 
|  | Constants = GetUnicodeString(br, size); | 
|  | break; | 
|  | case 0x0D: | 
|  | uint sizeLibID = br.ReadUInt32(); | 
|  | var regRef = new ExcelVbaReference(); | 
|  | regRef.Name = referenceName; | 
|  | regRef.ReferenceRecordID = id; | 
|  | regRef.Libid = GetString(br, sizeLibID); | 
|  | uint reserved1 = br.ReadUInt32(); | 
|  | ushort reserved2 = br.ReadUInt16(); | 
|  | References.Add(regRef); | 
|  | break; | 
|  | case 0x0E: | 
|  | var projRef = new ExcelVbaReferenceProject(); | 
|  | projRef.ReferenceRecordID = id; | 
|  | projRef.Name = referenceName; | 
|  | sizeLibID = br.ReadUInt32(); | 
|  | projRef.Libid = GetString(br, sizeLibID); | 
|  | sizeLibID = br.ReadUInt32(); | 
|  | projRef.LibIdRelative = GetString(br, sizeLibID); | 
|  | projRef.MajorVersion = br.ReadUInt32(); | 
|  | projRef.MinorVersion = br.ReadUInt16(); | 
|  | References.Add(projRef); | 
|  | break; | 
|  | case 0x0F: | 
|  | ushort modualCount = br.ReadUInt16(); | 
|  | break; | 
|  | case 0x13: | 
|  | ushort cookie = br.ReadUInt16(); | 
|  | break; | 
|  | case 0x14: | 
|  | LcidInvoke = (int)br.ReadUInt32(); | 
|  | break; | 
|  | case 0x16: | 
|  | referenceName = GetUnicodeString(br, size); | 
|  | break; | 
|  | case 0x19: | 
|  | currentModule = new ExcelVBAModule(); | 
|  | currentModule.Name = GetUnicodeString(br, size); | 
|  | Modules.Add(currentModule); | 
|  | break; | 
|  | case 0x1A: | 
|  | currentModule.streamName = GetUnicodeString(br, size); | 
|  | break; | 
|  | case 0x1C: | 
|  | currentModule.Description = GetUnicodeString(br, size); | 
|  | break; | 
|  | case 0x1E: | 
|  | currentModule.HelpContext = (int)br.ReadUInt32(); | 
|  | break; | 
|  | case 0x21: | 
|  | case 0x22: | 
|  | break; | 
|  | case 0x2B:      //Modul Terminator | 
|  | break; | 
|  | case 0x2C: | 
|  | currentModule.Cookie = br.ReadUInt16(); | 
|  | break; | 
|  | case 0x31: | 
|  | currentModule.ModuleOffset = br.ReadUInt32(); | 
|  | break; | 
|  | case 0x10: | 
|  | terminate = true; | 
|  | break; | 
|  | case 0x30: | 
|  | var extRef = (ExcelVbaReferenceControl)currentRef; | 
|  | var sizeExt = br.ReadUInt32(); | 
|  | extRef.LibIdExternal = GetString(br, sizeExt); | 
|  |  | 
|  | uint reserved4 = br.ReadUInt32(); | 
|  | ushort reserved5 = br.ReadUInt16(); | 
|  | extRef.OriginalTypeLib = new Guid(br.ReadBytes(16)); | 
|  | extRef.Cookie = br.ReadUInt32(); | 
|  | break; | 
|  | case 0x33: | 
|  | currentRef = new ExcelVbaReferenceControl(); | 
|  | currentRef.ReferenceRecordID = id; | 
|  | currentRef.Name = referenceName; | 
|  | currentRef.Libid = GetString(br, size); | 
|  | References.Add(currentRef); | 
|  | break; | 
|  | case 0x2F: | 
|  | var contrRef = (ExcelVbaReferenceControl)currentRef; | 
|  | contrRef.ReferenceRecordID = id; | 
|  |  | 
|  | var sizeTwiddled = br.ReadUInt32(); | 
|  | contrRef.LibIdTwiddled = GetString(br, sizeTwiddled); | 
|  | var r1 = br.ReadUInt32(); | 
|  | var r2 = br.ReadUInt16(); | 
|  |  | 
|  | break; | 
|  | case 0x25: | 
|  | currentModule.ReadOnly = true; | 
|  | break; | 
|  | case 0x28: | 
|  | currentModule.Private = true; | 
|  | break; | 
|  | default: | 
|  | break; | 
|  | } | 
|  | } | 
|  | } | 
|  | #endregion | 
|  |  | 
|  | #region Save Project | 
|  | internal void Save() | 
|  | { | 
|  | if (Validate()) | 
|  | { | 
|  | CompoundDocument doc = new CompoundDocument(); | 
|  | doc.Storage = new CompoundDocument.StoragePart(); | 
|  | var store = new CompoundDocument.StoragePart(); | 
|  | doc.Storage.SubStorage.Add("VBA", store); | 
|  |  | 
|  | store.DataStreams.Add("_VBA_PROJECT", CreateVBAProjectStream()); | 
|  | store.DataStreams.Add("dir", CreateDirStream()); | 
|  | foreach (var module in Modules) | 
|  | { | 
|  | store.DataStreams.Add(module.Name, CompoundDocument.CompressPart(Encoding.GetEncoding(CodePage).GetBytes(module.Attributes.GetAttributeText() + module.Code))); | 
|  | } | 
|  |  | 
|  | //Copy streams from the template, if used. | 
|  | if (Document != null) | 
|  | { | 
|  | foreach (var ss in Document.Storage.SubStorage) | 
|  | { | 
|  | if (ss.Key != "VBA") | 
|  | { | 
|  | doc.Storage.SubStorage.Add(ss.Key, ss.Value); | 
|  | } | 
|  | } | 
|  | foreach (var s in Document.Storage.DataStreams) | 
|  | { | 
|  | if (s.Key != "dir" && s.Key != "PROJECT" && s.Key != "PROJECTwm") | 
|  | { | 
|  | doc.Storage.DataStreams.Add(s.Key, s.Value); | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | doc.Storage.DataStreams.Add("PROJECT", CreateProjectStream()); | 
|  | doc.Storage.DataStreams.Add("PROJECTwm", CreateProjectwmStream()); | 
|  |  | 
|  | if (Part == null) | 
|  | { | 
|  | Uri = new Uri(PartUri, UriKind.Relative); | 
|  | Part = _pck.CreatePart(Uri, ExcelPackage.schemaVBA); | 
|  | var rel = _wb.Part.CreateRelationship(Uri, Packaging.TargetMode.Internal, schemaRelVba); | 
|  | } | 
|  | var vbaBuffer=doc.Save(); | 
|  | var st = Part.GetStream(FileMode.Create); | 
|  | st.Write(vbaBuffer, 0, vbaBuffer.Length); | 
|  | st.Flush(); | 
|  | //Save the digital signture | 
|  | Signature.Save(this); | 
|  | } | 
|  | } | 
|  |  | 
|  | private bool Validate() | 
|  | { | 
|  | Description = Description ?? ""; | 
|  | HelpFile1 = HelpFile1 ?? ""; | 
|  | HelpFile2 = HelpFile2 ?? ""; | 
|  | Constants = Constants ?? ""; | 
|  | return true; | 
|  | } | 
|  |  | 
|  | /// <summary> | 
|  | /// MS-OVBA 2.3.4.1 | 
|  | /// </summary> | 
|  | /// <returns></returns> | 
|  | private byte[] CreateVBAProjectStream() | 
|  | { | 
|  | BinaryWriter bw = new BinaryWriter(new MemoryStream()); | 
|  | bw.Write((ushort)0x61CC); //Reserved1 | 
|  | bw.Write((ushort)0xFFFF); //Version | 
|  | bw.Write((byte)0x0); //Reserved3 | 
|  | bw.Write((ushort)0x0); //Reserved4 | 
|  | return ((MemoryStream)bw.BaseStream).ToArray(); | 
|  | } | 
|  | /// <summary> | 
|  | /// MS-OVBA 2.3.4.1 | 
|  | /// </summary> | 
|  | /// <returns></returns> | 
|  | private byte[] CreateDirStream() | 
|  | { | 
|  | BinaryWriter bw = new BinaryWriter(new MemoryStream()); | 
|  |  | 
|  | /****** PROJECTINFORMATION Record ******/ | 
|  | bw.Write((ushort)1);        //ID | 
|  | bw.Write((uint)4);          //Size | 
|  | bw.Write((uint)SystemKind); //SysKind | 
|  |  | 
|  | bw.Write((ushort)2);        //ID | 
|  | bw.Write((uint)4);          //Size | 
|  | bw.Write((uint)Lcid);       //Lcid | 
|  |  | 
|  | bw.Write((ushort)0x14);     //ID | 
|  | bw.Write((uint)4);          //Size | 
|  | bw.Write((uint)LcidInvoke); //Lcid Invoke | 
|  |  | 
|  | bw.Write((ushort)3);        //ID | 
|  | bw.Write((uint)2);          //Size | 
|  | bw.Write((ushort)CodePage);   //Codepage | 
|  |  | 
|  | //ProjectName | 
|  | bw.Write((ushort)4);                                            //ID | 
|  | bw.Write((uint)Name.Length);                             //Size | 
|  | bw.Write(Encoding.GetEncoding(CodePage).GetBytes(Name)); //Project Name | 
|  |  | 
|  | //Description | 
|  | bw.Write((ushort)5);                                            //ID | 
|  | bw.Write((uint)Description.Length);                             //Size | 
|  | bw.Write(Encoding.GetEncoding(CodePage).GetBytes(Description)); //Project Name | 
|  | bw.Write((ushort)0x40);                                           //ID | 
|  | bw.Write((uint)Description.Length*2);                           //Size | 
|  | bw.Write(Encoding.Unicode.GetBytes(Description));               //Project Description | 
|  |  | 
|  | //Helpfiles | 
|  | bw.Write((ushort)6);                                           //ID | 
|  | bw.Write((uint)HelpFile1.Length);                              //Size | 
|  | bw.Write(Encoding.GetEncoding(CodePage).GetBytes(HelpFile1));  //HelpFile1 | 
|  | bw.Write((ushort)0x3D);                                           //ID | 
|  | bw.Write((uint)HelpFile2.Length);                              //Size | 
|  | bw.Write(Encoding.GetEncoding(CodePage).GetBytes(HelpFile2));  //HelpFile2 | 
|  |  | 
|  | //Help context id | 
|  | bw.Write((ushort)7);            //ID | 
|  | bw.Write((uint)4);              //Size | 
|  | bw.Write((uint)HelpContextID);  //Help context id | 
|  |  | 
|  | //Libflags | 
|  | bw.Write((ushort)8);            //ID | 
|  | bw.Write((uint)4);              //Size | 
|  | bw.Write((uint)0);  //Help context id | 
|  |  | 
|  | //Vba Version | 
|  | bw.Write((ushort)9);            //ID | 
|  | bw.Write((uint)4);              //Reserved | 
|  | bw.Write((uint)MajorVersion);   //Reserved | 
|  | bw.Write((ushort)MinorVersion); //Help context id | 
|  |  | 
|  | //Constants | 
|  | bw.Write((ushort)0x0C);           //ID | 
|  | bw.Write((uint)Constants.Length);              //Size | 
|  | bw.Write(Encoding.GetEncoding(CodePage).GetBytes(Constants));              //Help context id | 
|  | bw.Write((ushort)0x3C);                                           //ID | 
|  | bw.Write((uint)Constants.Length/2);                              //Size | 
|  | bw.Write(Encoding.Unicode.GetBytes(Constants));  //HelpFile2 | 
|  |  | 
|  | /****** PROJECTREFERENCES Record ******/ | 
|  | foreach (var reference in References) | 
|  | { | 
|  | WriteNameReference(bw, reference); | 
|  |  | 
|  | if (reference.ReferenceRecordID == 0x2F) | 
|  | { | 
|  | WriteControlReference(bw, reference); | 
|  | } | 
|  | else if (reference.ReferenceRecordID == 0x33) | 
|  | { | 
|  | WriteOrginalReference(bw, reference); | 
|  | } | 
|  | else if (reference.ReferenceRecordID == 0x0D) | 
|  | { | 
|  | WriteRegisteredReference(bw, reference); | 
|  | } | 
|  | else if (reference.ReferenceRecordID == 0x0E) | 
|  | { | 
|  | WriteProjectReference(bw, reference); | 
|  | } | 
|  | } | 
|  |  | 
|  | bw.Write((ushort)0x0F); | 
|  | bw.Write((uint)0x02); | 
|  | bw.Write((ushort)Modules.Count); | 
|  | bw.Write((ushort)0x13); | 
|  | bw.Write((uint)0x02); | 
|  | bw.Write((ushort)0xFFFF); | 
|  |  | 
|  | foreach (var module in Modules) | 
|  | { | 
|  | WriteModuleRecord(bw, module); | 
|  | } | 
|  | bw.Write((ushort)0x10);             //Terminator | 
|  | bw.Write((uint)0); | 
|  |  | 
|  | return CompoundDocument.CompressPart(((MemoryStream)bw.BaseStream).ToArray()); | 
|  | } | 
|  |  | 
|  | private void WriteModuleRecord(BinaryWriter bw, ExcelVBAModule module) | 
|  | { | 
|  | bw.Write((ushort)0x19); | 
|  | bw.Write((uint)module.Name.Length); | 
|  | bw.Write(Encoding.GetEncoding(CodePage).GetBytes(module.Name));     //Name | 
|  |  | 
|  | bw.Write((ushort)0x47); | 
|  | bw.Write((uint)module.Name.Length*2); | 
|  | bw.Write(Encoding.Unicode.GetBytes(module.Name));                   //Name | 
|  |  | 
|  | bw.Write((ushort)0x1A); | 
|  | bw.Write((uint)module.Name.Length); | 
|  | bw.Write(Encoding.GetEncoding(CodePage).GetBytes(module.Name));     //Stream Name | 
|  |  | 
|  | bw.Write((ushort)0x32); | 
|  | bw.Write((uint)module.Name.Length*2); | 
|  | bw.Write(Encoding.Unicode.GetBytes(module.Name));                   //Stream Name | 
|  |  | 
|  | module.Description = module.Description ?? ""; | 
|  | bw.Write((ushort)0x1C); | 
|  | bw.Write((uint)module.Description.Length); | 
|  | bw.Write(Encoding.GetEncoding(CodePage).GetBytes(module.Description));     //Description | 
|  |  | 
|  | bw.Write((ushort)0x48); | 
|  | bw.Write((uint)module.Description.Length*2); | 
|  | bw.Write(Encoding.Unicode.GetBytes(module.Description));                   //Description | 
|  |  | 
|  | bw.Write((ushort)0x31); | 
|  | bw.Write((uint)4); | 
|  | bw.Write((uint)0);                              //Module Stream Offset (No PerformanceCache) | 
|  |  | 
|  | bw.Write((ushort)0x1E); | 
|  | bw.Write((uint)4); | 
|  | bw.Write((uint)module.HelpContext);            //Help context ID | 
|  |  | 
|  | bw.Write((ushort)0x2C); | 
|  | bw.Write((uint)2); | 
|  | bw.Write((ushort)0xFFFF);            //Help context ID | 
|  |  | 
|  | bw.Write((ushort)(module.Type == eModuleType.Module ? 0x21 : 0x22)); | 
|  | bw.Write((uint)0); | 
|  |  | 
|  | if (module.ReadOnly) | 
|  | { | 
|  | bw.Write((ushort)0x25); | 
|  | bw.Write((uint)0);              //Readonly | 
|  | } | 
|  |  | 
|  | if (module.Private) | 
|  | { | 
|  | bw.Write((ushort)0x28); | 
|  | bw.Write((uint)0);              //Private | 
|  | } | 
|  |  | 
|  | bw.Write((ushort)0x2B);             //Terminator | 
|  | bw.Write((uint)0); | 
|  | } | 
|  |  | 
|  | private void WriteNameReference(BinaryWriter bw, ExcelVbaReference reference) | 
|  | { | 
|  | //Name record | 
|  | bw.Write((ushort)0x16);                                             //ID | 
|  | bw.Write((uint)reference.Name.Length);                              //Size | 
|  | bw.Write(Encoding.GetEncoding(CodePage).GetBytes(reference.Name));  //HelpFile1 | 
|  | bw.Write((ushort)0x3E);                                             //ID | 
|  | bw.Write((uint)reference.Name.Length * 2);                            //Size | 
|  | bw.Write(Encoding.Unicode.GetBytes(reference.Name));                //HelpFile2 | 
|  | } | 
|  | private void WriteControlReference(BinaryWriter bw, ExcelVbaReference reference) | 
|  | { | 
|  | WriteOrginalReference(bw, reference); | 
|  |  | 
|  | bw.Write((ushort)0x2F); | 
|  | var controlRef=(ExcelVbaReferenceControl)reference; | 
|  | bw.Write((uint)(4 + controlRef.LibIdTwiddled.Length + 4 + 2));    // Size of SizeOfLibidTwiddled, LibidTwiddled, Reserved1, and Reserved2. | 
|  | bw.Write((uint)controlRef.LibIdTwiddled.Length);                              //Size | 
|  | bw.Write(Encoding.GetEncoding(CodePage).GetBytes(controlRef.LibIdTwiddled));  //LibID | 
|  | bw.Write((uint)0);      //Reserved1 | 
|  | bw.Write((ushort)0);    //Reserved2 | 
|  | WriteNameReference(bw, reference);  //Name record again | 
|  | bw.Write((ushort)0x30); //Reserved3 | 
|  | bw.Write((uint)(4 + controlRef.LibIdExternal.Length + 4 + 2 + 16 + 4));    //Size of SizeOfLibidExtended, LibidExtended, Reserved4, Reserved5, OriginalTypeLib, and Cookie | 
|  | bw.Write((uint)controlRef.LibIdExternal.Length);                              //Size | 
|  | bw.Write(Encoding.GetEncoding(CodePage).GetBytes(controlRef.LibIdExternal));  //LibID | 
|  | bw.Write((uint)0);      //Reserved4 | 
|  | bw.Write((ushort)0);    //Reserved5 | 
|  | bw.Write(controlRef.OriginalTypeLib.ToByteArray()); | 
|  | bw.Write((uint)controlRef.Cookie);      //Cookie | 
|  | } | 
|  |  | 
|  | private void WriteOrginalReference(BinaryWriter bw, ExcelVbaReference reference) | 
|  | { | 
|  | bw.Write((ushort)0x33); | 
|  | bw.Write((uint)reference.Libid.Length); | 
|  | bw.Write(Encoding.GetEncoding(CodePage).GetBytes(reference.Libid));  //LibID | 
|  | } | 
|  | private void WriteProjectReference(BinaryWriter bw, ExcelVbaReference reference) | 
|  | { | 
|  | bw.Write((ushort)0x0E); | 
|  | var projRef = (ExcelVbaReferenceProject)reference; | 
|  | bw.Write((uint)(4 + projRef.Libid.Length + 4 + projRef.LibIdRelative.Length+4+2)); | 
|  | bw.Write((uint)projRef.Libid.Length); | 
|  | bw.Write(Encoding.GetEncoding(CodePage).GetBytes(projRef.Libid));  //LibAbsolute | 
|  | bw.Write((uint)projRef.LibIdRelative.Length); | 
|  | bw.Write(Encoding.GetEncoding(CodePage).GetBytes(projRef.LibIdRelative));  //LibIdRelative | 
|  | bw.Write(projRef.MajorVersion); | 
|  | bw.Write(projRef.MinorVersion); | 
|  | } | 
|  |  | 
|  | private void WriteRegisteredReference(BinaryWriter bw, ExcelVbaReference reference) | 
|  | { | 
|  | bw.Write((ushort)0x0D); | 
|  | bw.Write((uint)(4+reference.Libid.Length+4+2)); | 
|  | bw.Write((uint)reference.Libid.Length); | 
|  | bw.Write(Encoding.GetEncoding(CodePage).GetBytes(reference.Libid));  //LibID | 
|  | bw.Write((uint)0);      //Reserved1 | 
|  | bw.Write((ushort)0);    //Reserved2 | 
|  | } | 
|  |  | 
|  | private byte[] CreateProjectwmStream() | 
|  | { | 
|  | BinaryWriter bw = new BinaryWriter(new MemoryStream()); | 
|  |  | 
|  | foreach (var module in Modules) | 
|  | { | 
|  | bw.Write(Encoding.GetEncoding(CodePage).GetBytes(module.Name));     //Name | 
|  | bw.Write((byte)0); //Null | 
|  | bw.Write(Encoding.Unicode.GetBytes(module.Name));                   //Name | 
|  | bw.Write((ushort)0); //Null | 
|  | } | 
|  | bw.Write((ushort)0); //Null | 
|  | return CompoundDocument.CompressPart(((MemoryStream)bw.BaseStream).ToArray()); | 
|  | } | 
|  | private byte[] CreateProjectStream() | 
|  | { | 
|  | StringBuilder sb = new StringBuilder(); | 
|  | sb.AppendFormat("ID=\"{0}\"\r\n", ProjectID); | 
|  | foreach(var module in Modules) | 
|  | { | 
|  | if (module.Type == eModuleType.Document) | 
|  | { | 
|  | sb.AppendFormat("Document={0}/&H00000000\r\n", module.Name); | 
|  | } | 
|  | else if (module.Type == eModuleType.Module) | 
|  | { | 
|  | sb.AppendFormat("Module={0}\r\n", module.Name); | 
|  | } | 
|  | else if (module.Type == eModuleType.Class) | 
|  | { | 
|  | sb.AppendFormat("Class={0}\r\n", module.Name); | 
|  | } | 
|  | else | 
|  | { | 
|  | //Designer | 
|  | sb.AppendFormat("Package={0}\r\n", module.ClassID); | 
|  | sb.AppendFormat("BaseClass={0}\r\n", module.Name); | 
|  | } | 
|  | } | 
|  | if (HelpFile1 != "") | 
|  | { | 
|  | sb.AppendFormat("HelpFile={0}\r\n", HelpFile1); | 
|  | } | 
|  | sb.AppendFormat("Name=\"{0}\"\r\n", Name); | 
|  | sb.AppendFormat("HelpContextID={0}\r\n", HelpContextID); | 
|  |  | 
|  | if (!string.IsNullOrEmpty(Description)) | 
|  | { | 
|  | sb.AppendFormat("Description=\"{0}\"\r\n", Description); | 
|  | } | 
|  | sb.AppendFormat("VersionCompatible32=\"393222000\"\r\n"); | 
|  |  | 
|  | sb.AppendFormat("CMG=\"{0}\"\r\n", WriteProtectionStat()); | 
|  | sb.AppendFormat("DPB=\"{0}\"\r\n", WritePassword()); | 
|  | sb.AppendFormat("GC=\"{0}\"\r\n\r\n", WriteVisibilityState()); | 
|  |  | 
|  | sb.Append("[Host Extender Info]\r\n"); | 
|  | sb.Append("&H00000001={3832D640-CF90-11CF-8E43-00A0C911005A};VBE;&H00000000\r\n"); | 
|  | sb.Append("\r\n"); | 
|  | sb.Append("[Workspace]\r\n"); | 
|  | foreach(var module in Modules) | 
|  | { | 
|  | sb.AppendFormat("{0}=0, 0, 0, 0, C \r\n",module.Name); | 
|  | } | 
|  | string s = sb.ToString(); | 
|  | return Encoding.GetEncoding(CodePage).GetBytes(s); | 
|  | } | 
|  | private string WriteProtectionStat() | 
|  | { | 
|  | int stat=(_protection.UserProtected ? 1:0) | | 
|  | (_protection.HostProtected ? 2:0) | | 
|  | (_protection.VbeProtected ? 4:0); | 
|  |  | 
|  | return Encrypt(BitConverter.GetBytes(stat)); | 
|  | } | 
|  | private string WritePassword() | 
|  | { | 
|  | byte[] nullBits=new byte[3]; | 
|  | byte[] nullKey = new byte[4]; | 
|  | byte[] nullHash = new byte[20]; | 
|  | if (Protection.PasswordKey == null) | 
|  | { | 
|  | return Encrypt(new byte[] { 0 }); | 
|  | } | 
|  | else | 
|  | { | 
|  | Array.Copy(Protection.PasswordKey, nullKey, 4); | 
|  | Array.Copy(Protection.PasswordHash, nullHash, 20); | 
|  |  | 
|  | //Set Null bits | 
|  | for (int i = 0; i < 24; i++) | 
|  | { | 
|  | byte bit = (byte)(128 >> (int)((i % 8))); | 
|  | if (i < 4) | 
|  | { | 
|  | if (nullKey[i] == 0) | 
|  | { | 
|  | nullKey[i] = 1; | 
|  | } | 
|  | else | 
|  | { | 
|  | nullBits[0] |= bit; | 
|  | } | 
|  | } | 
|  | else | 
|  | { | 
|  | if (nullHash[i - 4] == 0) | 
|  | { | 
|  | nullHash[i - 4] = 1; | 
|  | } | 
|  | else | 
|  | { | 
|  | int byteIndex = (i - i % 8) / 8; | 
|  | nullBits[byteIndex] |= bit; | 
|  | } | 
|  | } | 
|  | } | 
|  | //Write the Password Hash Data Structure (2.4.4.1) | 
|  | BinaryWriter bw = new BinaryWriter(new MemoryStream()); | 
|  | bw.Write((byte)0xFF); | 
|  | bw.Write(nullBits); | 
|  | bw.Write(nullKey); | 
|  | bw.Write(nullHash); | 
|  | bw.Write((byte)0); | 
|  | return Encrypt(((MemoryStream)bw.BaseStream).ToArray()); | 
|  | } | 
|  | } | 
|  | private string WriteVisibilityState() | 
|  | { | 
|  | return Encrypt(new byte[] { (byte)(Protection.VisibilityState ? 0xFF : 0) }); | 
|  | } | 
|  | #endregion | 
|  | private string GetString(BinaryReader br, uint size) | 
|  | { | 
|  | return GetString(br, size, System.Text.Encoding.GetEncoding(CodePage)); | 
|  | } | 
|  | private string GetString(BinaryReader br, uint size, Encoding enc) | 
|  | { | 
|  | if (size > 0) | 
|  | { | 
|  | byte[] byteTemp = new byte[size]; | 
|  | byteTemp = br.ReadBytes((int)size); | 
|  | return enc.GetString(byteTemp); | 
|  | } | 
|  | else | 
|  | { | 
|  | return ""; | 
|  | } | 
|  | } | 
|  | private string GetUnicodeString(BinaryReader br, uint size) | 
|  | { | 
|  | string s = GetString(br, size); | 
|  | int reserved = br.ReadUInt16(); | 
|  | uint sizeUC = br.ReadUInt32(); | 
|  | string sUC = GetString(br, sizeUC, System.Text.Encoding.Unicode); | 
|  | return sUC.Length == 0 ? s : sUC; | 
|  | } | 
|  | internal CompoundDocument Document { get; set; } | 
|  | #endif | 
|  | internal Packaging.ZipPackagePart Part { get; set; } | 
|  | internal Uri Uri { get; private set; } | 
|  | #if !MONO | 
|  | /// <summary> | 
|  | /// Create a new VBA Project | 
|  | /// </summary> | 
|  | internal void Create() | 
|  | { | 
|  | if(Lcid>0) | 
|  | { | 
|  | throw (new InvalidOperationException("Package already contains a VBAProject")); | 
|  | } | 
|  | ProjectID = "{5DD90D76-4904-47A2-AF0D-D69B4673604E}"; | 
|  | Name = "VBAProject"; | 
|  | SystemKind = eSyskind.Win32;            //Default | 
|  | Lcid = 1033;                            //English - United States | 
|  | LcidInvoke = 1033;                      //English - United States | 
|  | CodePage = Encoding.Default.CodePage; | 
|  | MajorVersion = 1361024421; | 
|  | MinorVersion = 6; | 
|  | HelpContextID = 0; | 
|  | Modules.Add(new ExcelVBAModule(_wb.CodeNameChange) { Name = "ThisWorkbook", Code = "", Attributes=GetDocumentAttributes("ThisWorkbook", "0{00020819-0000-0000-C000-000000000046}"), Type = eModuleType.Document, HelpContext = 0 }); | 
|  | foreach (var sheet in _wb.Worksheets) | 
|  | { | 
|  | var name = GetModuleNameFromWorksheet(sheet); | 
|  | if (!Modules.Exists(name)) | 
|  | { | 
|  | Modules.Add(new ExcelVBAModule(sheet.CodeNameChange) { Name = name, Code = "", Attributes = GetDocumentAttributes(sheet.Name, "0{00020820-0000-0000-C000-000000000046}"), Type = eModuleType.Document, HelpContext = 0 }); | 
|  | } | 
|  | } | 
|  | _protection = new ExcelVbaProtection(this) { UserProtected = false, HostProtected = false, VbeProtected = false, VisibilityState = true }; | 
|  | } | 
|  |  | 
|  | internal string GetModuleNameFromWorksheet(ExcelWorksheet sheet) | 
|  | { | 
|  | var name = sheet.Name; | 
|  | if (name.Any(c => c > 255) || this.Modules[name] != null) | 
|  | { | 
|  | int i = sheet.PositionID; | 
|  | name = "Sheet" + i.ToString(); | 
|  | while (this.Modules[name] != null) | 
|  | { | 
|  | name = "Sheet" + (++i).ToString(); ; | 
|  | } | 
|  | } | 
|  | return name; | 
|  | } | 
|  | internal ExcelVbaModuleAttributesCollection GetDocumentAttributes(string name, string clsid) | 
|  | { | 
|  | var attr = new ExcelVbaModuleAttributesCollection(); | 
|  | attr._list.Add(new ExcelVbaModuleAttribute() { Name = "VB_Name", Value = name, DataType = eAttributeDataType.String }); | 
|  | attr._list.Add(new ExcelVbaModuleAttribute() { Name = "VB_Base", Value = clsid, DataType = eAttributeDataType.String }); | 
|  | attr._list.Add(new ExcelVbaModuleAttribute() { Name = "VB_GlobalNameSpace", Value = "False", DataType = eAttributeDataType.NonString }); | 
|  | attr._list.Add(new ExcelVbaModuleAttribute() { Name = "VB_Creatable", Value = "False", DataType = eAttributeDataType.NonString }); | 
|  | attr._list.Add(new ExcelVbaModuleAttribute() { Name = "VB_PredeclaredId", Value = "True", DataType = eAttributeDataType.NonString }); | 
|  | attr._list.Add(new ExcelVbaModuleAttribute() { Name = "VB_Exposed", Value = "False", DataType = eAttributeDataType.NonString }); | 
|  | attr._list.Add(new ExcelVbaModuleAttribute() { Name = "VB_TemplateDerived", Value = "False", DataType = eAttributeDataType.NonString }); | 
|  | attr._list.Add(new ExcelVbaModuleAttribute() { Name = "VB_Customizable", Value = "True", DataType = eAttributeDataType.NonString }); | 
|  |  | 
|  | return attr; | 
|  | } | 
|  |  | 
|  |  | 
|  | //internal string GetBlankDocumentModule(string name, string clsid) | 
|  | //{ | 
|  | //    string ret=string.Format("Attribute VB_Name = \"{0}\"\r\n",name); | 
|  | //    ret += string.Format("Attribute VB_Base = \"{0}\"\r\n", clsid);  //Microsoft.Office.Interop.Excel.WorksheetClass | 
|  | //    ret += "Attribute VB_GlobalNameSpace = False\r\n"; | 
|  | //    ret += "Attribute VB_Creatable = False\r\n"; | 
|  | //    ret += "Attribute VB_PredeclaredId = True\r\n"; | 
|  | //    ret += "Attribute VB_Exposed = True\r\n"; | 
|  | //    ret += "Attribute VB_TemplateDerived = False\r\n"; | 
|  | //    ret += "Attribute VB_Customizable = True"; | 
|  | //    return ret; | 
|  | //} | 
|  | //internal string GetBlankModule(string name) | 
|  | //{ | 
|  | //    return string.Format("Attribute VB_Name = \"{0}\"\r\n", name); | 
|  | //} | 
|  | //internal string GetBlankClassModule(string name, bool exposed) | 
|  | //{ | 
|  | //    string ret=string.Format("Attribute VB_Name = \"{0}\"\r\n",name); | 
|  | //    ret += string.Format("Attribute VB_Base = \"{0}\"\r\n", "0{FCFB3D2A-A0FA-1068-A738-08002B3371B5}"); | 
|  | //    ret += "Attribute VB_GlobalNameSpace = False\r\n"; | 
|  | //    ret += "Attribute VB_Creatable = False\r\n"; | 
|  | //    ret += "Attribute VB_PredeclaredId = False\r\n"; | 
|  | //    ret += string.Format("Attribute VB_Exposed = {0}\r\n", exposed ? "True" : "False"); | 
|  | //    ret += "Attribute VB_TemplateDerived = False\r\n"; | 
|  | //    ret += "Attribute VB_Customizable = False\r\n"; | 
|  | //    return ret; | 
|  | //} | 
|  | #endif | 
|  | /// <summary> | 
|  | /// Remove the project from the package | 
|  | /// </summary> | 
|  | public void Remove() | 
|  | { | 
|  | if (Part == null) return; | 
|  |  | 
|  | foreach (var rel in Part.GetRelationships()) | 
|  | { | 
|  | _pck.DeleteRelationship(rel.Id); | 
|  | } | 
|  | if (_pck.PartExists(Uri)) | 
|  | { | 
|  | _pck.DeletePart(Uri); | 
|  | } | 
|  | Part = null; | 
|  | Modules.Clear(); | 
|  | References.Clear(); | 
|  | Lcid = 0; | 
|  | LcidInvoke = 0; | 
|  | CodePage = 0; | 
|  | MajorVersion = 0; | 
|  | MinorVersion = 0; | 
|  | HelpContextID = 0; | 
|  | } | 
|  | public override string ToString() | 
|  | { | 
|  | return Name; | 
|  | } | 
|  | } | 
|  | } |