Beispiel #1
0
 /// <summary>
 ///
 /// </summary>
 /// <param name="dbPath">dbFilePath must point to the DIT file on the local computer.</param>
 /// <param name="logPath">The path should point to a writeable folder on the local computer, where ESE log files will be created. If not specified, then temp folder will be used.</param>
 public DirectoryContext(string dbFilePath, bool readOnly, string logDirectoryPath = null)
 {
     if (!File.Exists(dbFilePath))
     {
         // TODO: Extract as resource
         throw new FileNotFoundException("The specified database file does not exist.", dbFilePath);
     }
     int pageSize = DirectoryContext.GetDBPageSize(dbFilePath);
     string dbDirectoryPath = Path.GetDirectoryName(dbFilePath);
     string checkpointDirectoryPath = dbDirectoryPath;
     string tempDirectoryPath = dbDirectoryPath;
     if (logDirectoryPath != null)
     {
         if (!Directory.Exists(logDirectoryPath))
         {
             // TODO: Extract as resource
             throw new FileNotFoundException("The specified log directory does not exist.", logDirectoryPath);
         }
     }
     else
     {
         logDirectoryPath = dbDirectoryPath;
     }
     // TODO: Exception handling?
     // HACK: IsamInstance constructor throws AccessDenied Exception when the path does not end with a backslash.
     // TODO: Const isam instance name
     string instanceName = "DSInternals";
     this.instance = new IsamInstance(AddPathSeparator(checkpointDirectoryPath), AddPathSeparator(logDirectoryPath), AddPathSeparator(tempDirectoryPath), ADConstants.EseBaseName, instanceName, readOnly, pageSize);
     try
     {
         var isamParameters = this.instance.IsamSystemParameters;
         // TODO: Add param explanations
         isamParameters.LogFileSize = ADConstants.EseLogFileSize;
         isamParameters.DeleteOutOfRangeLogs = true;
         isamParameters.EnableIndexChecking = 1;
         isamParameters.EnableIndexCleanup = true;
         isamParameters.CircularLog = true;
         // TODO: Configure additional ISAM parameters
         // this.instance.IsamSystemParameters.EnableOnlineDefrag = false;
         // JET_paramDeleteOldLogs =  1
         this.session = this.instance.CreateSession();
         this.session.AttachDatabase(dbFilePath);
         this.attachedDatabasePath = dbFilePath;
         this.database = this.session.OpenDatabase(dbFilePath);
         this.Schema = new DirectorySchema(this.database);
         this.SecurityDescriptorRersolver = new SecurityDescriptorRersolver(this.database);
         this.DistinguishedNameResolver = new DistinguishedNameResolver(this.database, this.Schema);
         this.LinkResolver = new LinkResolver(this.database, this.Schema);
         this.DomainController = new DomainController(this);
     }
     catch
     {
         // Free resources if anything failed
         this.Dispose();
         throw;
     }
 }
Beispiel #2
0
 // TODO: Internal?
 // TODO: ISchema
 public DirectorySchema(IsamDatabase database)
 {
     TableDefinition dataTable = database.Tables[ADConstants.DataTableName];
     this.LoadColumnList(dataTable.Columns);
     this.LoadAttributeIndices(dataTable.Indices);
     using (var cursor = database.OpenCursor(ADConstants.DataTableName))
     {
         this.LoadClassList(cursor);
         this.LoadAttributeProperties(cursor);
         this.LoadPrefixMap(cursor);
     }
     // TODO: Load Ext-Int Map from hiddentable
 }
Beispiel #3
0
        public LinkResolver(IsamDatabase database, DirectorySchema schema)
        {
            this.schema = schema;
            this.cursor = database.OpenCursor(ADConstants.LinkTableName);
            if (this.cursor.TableDefinition.Indices.Contains(linkIndex2008))
            {
                this.cursor.SetCurrentIndex(linkIndex2008);
            }
            else
            {
                // Fallback to the old index if the newer one does not exist
                cursor.SetCurrentIndex(linkIndex2003);
            }

            // TODO: Load column ids instead of names
        }
Beispiel #4
0
        /// <summary>
        /// Creates a <see cref="ColumnDefinition"/> object representing the column passed in by <paramref name="columnList"/>.
        /// </summary>
        /// <param name="database">The database.</param>
        /// <param name="tableName">Name of the table.</param>
        /// <param name="columnList">The <see cref="JET_COLUMNLIST"/> object that represents the row in
        /// the temptable for this particular column.</param>
        /// <returns>
        /// A <see cref="ColumnDefinition"/> object based on the current row in the temptable
        /// represented by <paramref name="columnList"/>.
        /// </returns>
        internal static ColumnDefinition Load(IsamDatabase database, string tableName, JET_COLUMNLIST columnList)
        {
            lock (database.IsamSession)
            {
                using (IsamTransaction trx = new IsamTransaction(database.IsamSession))
                {
                    // load info for the column
                    ColumnDefinition columnDefinition = new ColumnDefinition();

                    JET_SESID sesid = database.IsamSession.Sesid;

                    // As of Sep 2015, JetGetColumnInfoW is only called for Win8+. Even though Unicode should have
                    // worked in Win7, it wasn't reliable until Win8.
                    Encoding encodingOfTextColumns = EsentVersion.SupportsWindows8Features ? Encoding.Unicode : LibraryHelpers.EncodingASCII;

                    string columnName = Api.RetrieveColumnAsString(
                        database.IsamSession.Sesid,
                        columnList.tableid,
                        columnList.columnidcolumnname,
                        encodingOfTextColumns);
                    JET_COLUMNBASE columnbase;
                    Api.JetGetColumnInfo(database.IsamSession.Sesid, database.Dbid, tableName, columnName, out columnbase);
                    columnDefinition.columnid = new Columnid(columnbase);
                    columnDefinition.name     = columnDefinition.columnid.Name;
                    columnDefinition.type     = columnDefinition.columnid.Type;

                    ColumndefGrbit grbitColumn = (ColumndefGrbit)Api.RetrieveColumnAsUInt32(sesid, columnList.tableid, columnList.columnidgrbit).GetValueOrDefault();
                    columnDefinition.flags = ColumnFlagsFromGrbits(grbitColumn);

                    columnDefinition.maxLength = Api.RetrieveColumnAsInt32(sesid, columnList.tableid, columnList.columnidcbMax).GetValueOrDefault();

                    columnDefinition.IsAscii = columnbase.cp == JET_CP.ASCII;
                    byte[] defaultValueBytes = Api.RetrieveColumn(sesid, columnList.tableid, columnList.columnidDefault);

                    Columnid isamColumnid = columnDefinition.columnid;
                    columnDefinition.defaultValue = Converter.ObjectFromBytes(
                        isamColumnid.Coltyp,
                        columnDefinition.IsAscii,
                        defaultValueBytes);

                    columnDefinition.ReadOnly = true;

                    return(columnDefinition);
                }
            }
        }
Beispiel #5
0
        /// <summary>
        /// Loads the specified table specified in the <see cref="JET_OBJECTINFO"/> object.
        /// </summary>
        /// <param name="database">The database.</param>
        /// <param name="tableName">Name of the table.</param>
        /// <param name="objectInfo">The object information.</param>
        /// <returns>A <see cref="TableDefinition"/> corresponding to the table specified in <paramref name="objectInfo"/>.</returns>
        internal static TableDefinition Load(IsamDatabase database, string tableName, JET_OBJECTINFO objectInfo)
        {
            lock (database.IsamSession)
            {
                // save the database
                TableDefinition tableDefinition = new TableDefinition();
                tableDefinition.database = database;

                // load info for the table
                tableDefinition.name = tableName;

                // create our column and index collections
                tableDefinition.columnCollection = new ColumnCollection(database, tableDefinition.name);
                tableDefinition.indexCollection  = new IndexCollection(database, tableDefinition.name);

                return(tableDefinition);
            }
        }
Beispiel #6
0
        /// <summary>
        /// Loads the specified table specified in the <see cref="JET_OBJECTLIST"/> object.
        /// </summary>
        /// <param name="database">The database.</param>
        /// <param name="objectList">The object list.</param>
        /// <returns>A <see cref="TableDefinition"/> corresponding to the table specified in <paramref name="objectList"/>.</returns>
        internal static TableDefinition Load(IsamDatabase database, JET_OBJECTLIST objectList)
        {
            lock (database.IsamSession)
            {
                // save the database
                TableDefinition tableDefinition = new TableDefinition();
                tableDefinition.database = database;

                // load info for the table
                tableDefinition.name = Api.RetrieveColumnAsString(
                    database.IsamSession.Sesid,
                    objectList.tableid,
                    objectList.columnidobjectname);

                // create our column and index collections
                tableDefinition.columnCollection = new ColumnCollection(database, tableDefinition.name);
                tableDefinition.indexCollection  = new IndexCollection(database, tableDefinition.name);

                return(tableDefinition);
            }
        }
Beispiel #7
0
 /// <summary>
 /// Initializes a new instance of the <see cref="TableEnumerator"/> class.
 /// </summary>
 /// <param name="database">The database.</param>
 internal TableEnumerator(IsamDatabase database)
 {
     this.database = database;
     this.enumerator = null;
 }
Beispiel #8
0
 /// <summary>
 /// Initializes a new instance of the <see cref="ColumnEnumerator"/> class.
 /// </summary>
 /// <param name="database">The database.</param>
 /// <param name="tableName">Name of the table.</param>
 internal ColumnEnumerator(IsamDatabase database, string tableName)
 {
     this.database   = database;
     this.tableName  = tableName;
     this.enumerator = null;
 }
Beispiel #9
0
 /// <summary>
 /// Initializes a new instance of the <see cref="TableCollection"/> class. 
 /// </summary>
 public TableCollection()
 {
     this.database = null;
 }
Beispiel #10
0
 /// <summary>
 /// Initializes a new instance of the <see cref="ColumnEnumerator"/> class.
 /// </summary>
 /// <param name="enumerator">The enumerator.</param>
 internal ColumnEnumerator(IDictionaryEnumerator enumerator)
 {
     this.database = null;
     this.enumerator = enumerator;
 }
Beispiel #11
0
 /// <summary>
 /// Initializes a new instance of the <see cref="ColumnCollection"/> class.
 /// </summary>
 /// <param name="database">The database.</param>
 /// <param name="tableName">Name of the table.</param>
 internal ColumnCollection(IsamDatabase database, string tableName)
 {
     this.database = database;
     this.tableName = tableName;
     this.readOnly = true;
 }
 public SecurityDescriptorRersolver(IsamDatabase database)
 {
     this.cursor = database.OpenCursor(ADConstants.SecurityDescriptorTableName);
     this.cursor.SetCurrentIndex(SdIndex);
 }
 /// <summary>
 /// Initializes a new instance of the <see cref="IndexCollection"/> class.
 /// </summary>
 /// <param name="database">The database.</param>
 /// <param name="tableName">Name of the table.</param>
 internal IndexCollection(IsamDatabase database, string tableName)
 {
     this.database  = database;
     this.tableName = tableName;
     this.readOnly  = true;
 }
Beispiel #14
0
        /// <summary>
        /// Initializes a new instance of the <see cref="Cursor"/> class.
        /// </summary>
        /// <param name="isamSession">The session.</param>
        /// <param name="database">The database.</param>
        /// <param name="tableName">Name of the table.</param>
        /// <param name="grbit">The grbit.</param>
        internal Cursor(IsamSession isamSession, IsamDatabase database, string tableName, OpenTableGrbit grbit)
        {
            lock (isamSession)
            {
                this.isamSession = isamSession;
                this.database = database;
                this.tableName = tableName;
                Api.JetOpenTable(isamSession.Sesid, database.Dbid, tableName, null, 0, grbit, out this.tableid);
                this.cleanup = true;
                this.record = new ColumnAccessor(this, isamSession, this.tableid, RetrieveColumnGrbit.None);
                this.editRecord = new ColumnAccessor(this, isamSession, this.tableid, RetrieveColumnGrbit.RetrieveCopy);
                this.indexRecord = new ColumnAccessor(this, isamSession, this.tableid, RetrieveColumnGrbit.RetrieveFromIndex);

                this.MoveBeforeFirst();
            }
        }
Beispiel #15
0
 /// <summary>
 /// Initializes a new instance of the <see cref="ColumnCollection"/> class.
 /// </summary>
 public ColumnCollection()
 {
     this.database = null;
 }
Beispiel #16
0
 /// <summary>
 /// Initializes a new instance of the <see cref="TableEnumerator"/> class.
 /// </summary>
 /// <param name="database">The database.</param>
 internal TableEnumerator(IsamDatabase database)
 {
     this.database   = database;
     this.enumerator = null;
 }
Beispiel #17
0
        /// <summary>
        /// Creates a <see cref="ColumnDefinition"/> object representing the column passed in by <paramref name="columnBase"/>.
        /// </summary>
        /// <param name="database">The database.</param>
        /// <param name="tableName">Name of the table.</param>
        /// <param name="columnBase">The <see cref="JET_COLUMNBASE"/> object that represents this particular column.</param>
        /// <returns>
        /// A <see cref="ColumnDefinition"/> object based on the <paramref name="columnBase"/> object.
        /// </returns>
        internal static ColumnDefinition Load(IsamDatabase database, string tableName, JET_COLUMNBASE columnBase)
        {
            lock (database.IsamSession)
            {
                using (IsamTransaction trx = new IsamTransaction(database.IsamSession))
                {
                    JET_SESID sesid = database.IsamSession.Sesid;

                    // load info for the column
                    ColumnDefinition columnDefinition = new ColumnDefinition();

                    columnDefinition.columnid = new Columnid(columnBase);
                    columnDefinition.name     = columnDefinition.columnid.Name;
                    columnDefinition.type     = columnDefinition.columnid.Type;

                    columnDefinition.flags = ColumnFlagsFromGrbits(columnBase.grbit);

                    columnDefinition.maxLength = (int)columnBase.cbMax;
                    columnDefinition.IsAscii   = columnBase.cp == JET_CP.ASCII;

                    // there is currently no efficient means to retrieve the
                    // default value of a specific column from JET.  so, we are
                    // going to reach into the catalog and fetch it directly
                    JET_TABLEID tableidCatalog;
                    Api.JetOpenTable(
                        sesid,
                        database.Dbid,
                        "MSysObjects",
                        null,
                        0,
                        OpenTableGrbit.ReadOnly,
                        out tableidCatalog);

                    Api.JetSetCurrentIndex(sesid, tableidCatalog, "RootObjects");
                    Api.MakeKey(sesid, tableidCatalog, true, MakeKeyGrbit.NewKey);
                    Api.MakeKey(
                        sesid,
                        tableidCatalog,
                        Converter.BytesFromObject(JET_coltyp.Text, true, columnBase.szBaseTableName),
                        MakeKeyGrbit.None);
                    Api.JetSeek(sesid, tableidCatalog, SeekGrbit.SeekEQ);
                    JET_COLUMNBASE columnbaseCatalog;
                    Api.JetGetTableColumnInfo(sesid, tableidCatalog, "ObjidTable", out columnbaseCatalog);
                    uint objidTable = Api.RetrieveColumnAsUInt32(sesid, tableidCatalog, columnbaseCatalog.columnid).GetValueOrDefault();

                    Api.JetSetCurrentIndex(sesid, tableidCatalog, "Name");
                    Api.MakeKey(sesid, tableidCatalog, objidTable, MakeKeyGrbit.NewKey);
                    Api.MakeKey(sesid, tableidCatalog, (short)2, MakeKeyGrbit.None);
                    Api.MakeKey(sesid, tableidCatalog, columnBase.szBaseColumnName, Encoding.ASCII, MakeKeyGrbit.None);
                    Api.JetSeek(sesid, tableidCatalog, SeekGrbit.SeekEQ);

                    Api.JetGetTableColumnInfo(sesid, tableidCatalog, "DefaultValue", out columnbaseCatalog);
                    byte[] defaultValueBytes = Api.RetrieveColumn(sesid, tableidCatalog, columnbaseCatalog.columnid);

                    Columnid isamColumnid = columnDefinition.columnid;
                    columnDefinition.defaultValue = Converter.ObjectFromBytes(
                        isamColumnid.Coltyp,
                        columnDefinition.IsAscii,
                        defaultValueBytes);

                    columnDefinition.ReadOnly = true;

                    return(columnDefinition);
                }
            }
        }
 /// <summary>
 /// Initializes a new instance of the <see cref="IndexCollection"/> class.
 /// </summary>
 public IndexCollection()
 {
     this.database = null;
 }
 /// <summary>
 /// Initializes a new instance of the <see cref="TableCollection"/> class.
 /// </summary>
 public TableCollection()
 {
     this.database = null;
 }
 /// <summary>
 /// Initializes a new instance of the <see cref="TableCollection"/> class.
 /// </summary>
 /// <param name="database">The database.</param>
 internal TableCollection(IsamDatabase database)
 {
     this.database = database;
     this.readOnly = true;
 }
Beispiel #21
0
        /// <summary>
        /// Creates an <see cref="IndexDefinition"/> object from the specified <paramref name="indexList"/>.
        /// </summary>
        /// <param name="database">The database.</param>
        /// <param name="tableName">Name of the table.</param>
        /// <param name="indexList">The index list.</param>
        /// <returns>An <see cref="IndexDefinition"/> object represting the specified index.</returns>
        internal static IndexDefinition Load(IsamDatabase database, string tableName, JET_INDEXLIST indexList)
        {
            lock (database.IsamSession)
            {
                JET_SESID sesid = database.IsamSession.Sesid;
                using (IsamTransaction trx = new IsamTransaction(database.IsamSession))
                {
                    // load info for the index
                    IndexDefinition indexDefinition = new IndexDefinition();

                    indexDefinition.name = Api.RetrieveColumnAsString(
                        sesid,
                        indexList.tableid,
                        indexList.columnidindexname);

                    CreateIndexGrbit grbitIndex = (CreateIndexGrbit)Api.RetrieveColumnAsUInt32(sesid, indexList.tableid, indexList.columnidgrbitIndex);
                    indexDefinition.flags = IndexFlagsFromGrbits(grbitIndex);

                    Api.JetGetIndexInfo(
                        sesid,
                        database.Dbid,
                        tableName,
                        indexDefinition.name,
                        out indexDefinition.density,
                        JET_IdxInfo.SpaceAlloc);
                    int lcid;
                    Api.JetGetIndexInfo(
                        database.IsamSession.Sesid,
                        database.Dbid,
                        tableName,
                        indexDefinition.name,
                        out lcid,
                        JET_IdxInfo.LCID);
                    indexDefinition.cultureInfo = new CultureInfo(lcid);

                    indexDefinition.compareOptions =
                        Conversions.CompareOptionsFromLCMapFlags(
                            Api.RetrieveColumnAsUInt32(
                                database.IsamSession.Sesid,
                                indexList.tableid,
                                indexList.columnidLCMapFlags).GetValueOrDefault());

                    // CONSIDER:  move this workaround into Isam.Interop
                    try
                    {
                        ushort maxKeyLength;
                        Api.JetGetIndexInfo(
                            database.IsamSession.Sesid,
                            database.Dbid,
                            tableName,
                            indexDefinition.name,
                            out maxKeyLength,
                            JET_IdxInfo.KeyMost);
                        indexDefinition.maxKeyLength = maxKeyLength;
                    }
                    catch (EsentInvalidParameterException)
                    {
                        indexDefinition.maxKeyLength = 255;
                    }
                    catch (EsentColumnNotFoundException)
                    {
                        indexDefinition.maxKeyLength = 255;
                    }

                    // load info for each key column in the index
                    int currentColumn      = 0;
                    int totalNumberColumns = Api.RetrieveColumnAsInt32(sesid, indexList.tableid, indexList.columnidcColumn).GetValueOrDefault();

                    indexDefinition.keyColumnCollection = new KeyColumnCollection();
                    do
                    {
                        // load info for this key column
                        IndexKeyGrbit grbitColumn = (IndexKeyGrbit)Api.RetrieveColumnAsUInt32(sesid, indexList.tableid, indexList.columnidgrbitColumn);
                        bool          isAscending = (grbitColumn & IndexKeyGrbit.Descending) == 0;
                        string        columnName  = Api.RetrieveColumnAsString(
                            sesid,
                            indexList.tableid,
                            indexList.columnidcolumnname);
                        JET_COLUMNBASE columnbase;
                        Api.JetGetColumnInfo(sesid, database.Dbid, tableName, columnName, out columnbase);

                        indexDefinition.keyColumnCollection.Add(new KeyColumn(new Columnid(columnbase), isAscending));

                        // move onto the next key column definition, unless it is
                        // the last key column
                        if (currentColumn != totalNumberColumns - 1)
                        {
                            Api.TryMoveNext(sesid, indexList.tableid);
                        }
                    }while (++currentColumn < totalNumberColumns);

                    indexDefinition.keyColumnCollection.ReadOnly = true;

                    // Vista: There is currently no efficient means to retrieve the
                    // conditional columns for an index from JET.  so, we are
                    // going to reach into the catalog and fetch them directly.
                    //
                    // FUTURE: Windows 7 introduced Windows7IdxInfo.CreateIndex and Windows7IdxInfo.CreateIndex2 (and
                    // Win8 has Windows8IdxInfo.CreateIndex3). Consider retrieving the conditional columns with that
                    // API and converting the results. But that does not solve the problem for Vista.
                    indexDefinition.conditionalColumnCollection = new ConditionalColumnCollection();
                    JET_TABLEID tableidCatalog;
                    Api.JetOpenTable(
                        database.IsamSession.Sesid,
                        database.Dbid,
                        "MSysObjects",
                        null,
                        0,
                        OpenTableGrbit.ReadOnly,
                        out tableidCatalog);

                    Api.JetSetCurrentIndex(sesid, tableidCatalog, "RootObjects");

                    Api.MakeKey(sesid, tableidCatalog, true, MakeKeyGrbit.NewKey);
                    Api.MakeKey(sesid, tableidCatalog, tableName, Encoding.ASCII, MakeKeyGrbit.None);
                    Api.JetSeek(sesid, tableidCatalog, SeekGrbit.SeekEQ);

                    JET_COLUMNID columnidTemp = Api.GetTableColumnid(sesid, tableidCatalog, "ObjidTable");
                    int          objidTable   = Api.RetrieveColumnAsInt32(sesid, tableidCatalog, columnidTemp).GetValueOrDefault();

                    Api.JetSetCurrentIndex(sesid, tableidCatalog, "Name");
                    Api.MakeKey(sesid, tableidCatalog, objidTable, MakeKeyGrbit.NewKey);
                    Api.MakeKey(sesid, tableidCatalog, (short)3, MakeKeyGrbit.None);
                    Api.MakeKey(sesid, tableidCatalog, indexDefinition.name, Encoding.ASCII, MakeKeyGrbit.None);
                    Api.JetSeek(sesid, tableidCatalog, SeekGrbit.SeekEQ);

                    columnidTemp = Api.GetTableColumnid(sesid, tableidCatalog, "Flags");
                    int indexFlagsBytes = Api.RetrieveColumnAsInt32(sesid, tableidCatalog, columnidTemp).GetValueOrDefault();

                    columnidTemp = Api.GetTableColumnid(sesid, tableidCatalog, "ConditionalColumns");
                    byte[] conditionalColumnsBytes = Api.RetrieveColumn(sesid, tableidCatalog, columnidTemp);

                    for (int ib = 0; conditionalColumnsBytes != null && ib < conditionalColumnsBytes.Length; ib += 4)
                    {
                        uint           colid;
                        bool           mustBeNull;
                        JET_COLUMNBASE columnBase;

                        // fIDXExtendedColumns
                        if ((indexFlagsBytes & 0xffff0000) == 0x00010000)
                        {
                            // fIDXSEGTemplateColumn
                            if ((conditionalColumnsBytes[ib + 0] & 0x80) != 0)
                            {
                                // fCOLUMNIDTemplate
                                colid = 0x80000000 | (uint)(conditionalColumnsBytes[ib + 3] << 8) | (uint)conditionalColumnsBytes[ib + 2];
                            }
                            else
                            {
                                colid = (uint)(conditionalColumnsBytes[ib + 3] << 8) | (uint)conditionalColumnsBytes[ib + 2];
                            }

                            // fIDXSEGMustBeNull
                            if ((conditionalColumnsBytes[ib + 0] & 0x20) != 0)
                            {
                                mustBeNull = true;
                            }
                            else
                            {
                                mustBeNull = false;
                            }
                        }
                        else
                        {
                            // do not load conditional columns from an unknown format
                            continue;
                        }

                        JET_COLUMNID castedColid = JET_COLUMNID.CreateColumnidFromNativeValue(unchecked ((int)colid));
                        VistaApi.JetGetColumnInfo(
                            database.IsamSession.Sesid,
                            database.Dbid,
                            tableName,
                            castedColid,
                            out columnBase);

                        indexDefinition.conditionalColumnCollection.Add(new ConditionalColumn(new Columnid(columnBase), mustBeNull));
                    }

                    indexDefinition.conditionalColumnCollection.ReadOnly = true;

                    indexDefinition.ReadOnly = true;

                    return(indexDefinition);
                }
            }
        }
Beispiel #22
0
 /// <summary>
 /// Initializes a new instance of the <see cref="ColumnCollection"/> class. 
 /// </summary>
 public ColumnCollection()
 {
     this.database = null;
 }
Beispiel #23
0
 protected virtual void Dispose(bool disposing)
 {
     if (!disposing)
     {
         // Do nothing
         return;
     }
     if(this.LinkResolver != null)
     {
         this.LinkResolver.Dispose();
         this.LinkResolver = null;
     }
     if (this.SecurityDescriptorRersolver != null)
     {
         this.SecurityDescriptorRersolver.Dispose();
         this.SecurityDescriptorRersolver = null;
     }
     if (this.DistinguishedNameResolver != null)
     {
         this.DistinguishedNameResolver.Dispose();
         this.DistinguishedNameResolver = null;
     }
     if (this.DomainController != null)
     {
         this.DomainController.Dispose();
         this.DomainController = null;
     }
     if (this.database != null)
     {
         this.database.Dispose();
         this.database = null;
     }
     if (this.session != null)
     {
         if (this.attachedDatabasePath != null)
         {
             this.session.DetachDatabase(this.attachedDatabasePath);
             this.attachedDatabasePath = null;
         }
         this.session.Dispose();
         this.session = null;
     }
     if (this.instance != null)
     {
         this.instance.Dispose();
         this.instance = null;
     }
 }
Beispiel #24
0
 /// <summary>
 /// Initializes a new instance of the <see cref="ColumnEnumerator"/> class.
 /// </summary>
 /// <param name="database">The database.</param>
 /// <param name="tableName">Name of the table.</param>
 internal ColumnEnumerator(IsamDatabase database, string tableName)
 {
     this.database = database;
     this.tableName = tableName;
     this.enumerator = null;
 }
 public DistinguishedNameResolver(IsamDatabase database, DirectorySchema schema)
 {
     this.dnCache = new Dictionary<int, string>();
     this.schema = schema;
     this.cursor = database.OpenCursor(ADConstants.DataTableName);
 }
Beispiel #26
0
        /// <summary>
        /// Creates a single table with the specified definition in the database
        /// </summary>
        /// <param name="tableDefinition">The table definition.</param>
        public override void CreateTable(TableDefinition tableDefinition)
        {
            lock (this.IsamSession)
            {
                this.CheckDisposed();

                using (IsamTransaction trx = new IsamTransaction(this.IsamSession))
                {
                    // FUTURE-2013/11/15-martinc: Consider using JetCreateTableColumnIndex(). It would be
                    // a bit faster because it's only a single managed/native transition.

                    // Hard-code the initial space and density.
                    JET_TABLEID tableid;
                    Api.JetCreateTable(this.IsamSession.Sesid, this.dbid, tableDefinition.Name, 16, 90, out tableid);

                    foreach (ColumnDefinition columnDefinition in tableDefinition.Columns)
                    {
                        JET_COLUMNDEF columndef = new JET_COLUMNDEF();
                        columndef.coltyp = IsamDatabase.ColtypFromColumnDefinition(columnDefinition);
                        columndef.cp     = JET_CP.Unicode;
                        columndef.cbMax  = columnDefinition.MaxLength;

                        columndef.grbit = Converter.ColumndefGrbitFromColumnFlags(columnDefinition.Flags);
                        byte[] defaultValueBytes = Converter.BytesFromObject(
                            columndef.coltyp,
                            false /*ASCII */,
                            columnDefinition.DefaultValue);

                        JET_COLUMNID columnid;
                        int          defaultValueLength = (defaultValueBytes == null) ? 0 : defaultValueBytes.Length;
                        Api.JetAddColumn(
                            this.IsamSession.Sesid,
                            tableid,
                            columnDefinition.Name,
                            columndef,
                            defaultValueBytes,
                            defaultValueLength,
                            out columnid);
                    }

                    foreach (IndexDefinition indexDefinition in tableDefinition.Indices)
                    {
                        JET_INDEXCREATE[] indexcreates = new JET_INDEXCREATE[1];
                        indexcreates[0] = new JET_INDEXCREATE();

                        indexcreates[0].szIndexName            = indexDefinition.Name;
                        indexcreates[0].szKey                  = IsamDatabase.IndexKeyFromIndexDefinition(indexDefinition);
                        indexcreates[0].cbKey                  = indexcreates[0].szKey.Length;
                        indexcreates[0].grbit                  = IsamDatabase.GrbitFromIndexDefinition(indexDefinition);
                        indexcreates[0].ulDensity              = indexDefinition.Density;
                        indexcreates[0].pidxUnicode            = new JET_UNICODEINDEX();
                        indexcreates[0].pidxUnicode.lcid       = indexDefinition.CultureInfo.LCID;
                        indexcreates[0].pidxUnicode.dwMapFlags = (uint)Converter.UnicodeFlagsFromCompareOptions(indexDefinition.CompareOptions);
                        indexcreates[0].rgconditionalcolumn    = IsamDatabase.ConditionalColumnsFromIndexDefinition(indexDefinition);
                        indexcreates[0].cConditionalColumn     = indexcreates[0].rgconditionalcolumn.Length;
                        indexcreates[0].cbKeyMost              = indexDefinition.MaxKeyLength;
                        Api.JetCreateIndex2(this.IsamSession.Sesid, tableid, indexcreates, indexcreates.Length);
                    }

                    // The initially-created tableid is opened exclusively.
                    Api.JetCloseTable(this.IsamSession.Sesid, tableid);
                    trx.Commit();
                    DatabaseCommon.SchemaUpdateID++;
                }
            }
        }
Beispiel #27
0
        /// <summary>
        /// Creates a <see cref="ColumnDefinition"/> object representing the column passed in by <paramref name="columnList"/>.
        /// </summary>
        /// <param name="database">The database.</param>
        /// <param name="tableName">Name of the table.</param>
        /// <param name="columnList">The <see cref="JET_COLUMNLIST"/> object that represents the row in
        /// the temptable for this particular column.</param>
        /// <returns>
        /// A <see cref="ColumnDefinition"/> object based on the current row in the temptable
        /// represented by <paramref name="columnList"/>.
        /// </returns>
        internal static ColumnDefinition Load(IsamDatabase database, string tableName, JET_COLUMNLIST columnList)
        {
            lock (database.IsamSession)
            {
                using (IsamTransaction trx = new IsamTransaction(database.IsamSession))
                {
                    // load info for the column
                    ColumnDefinition columnDefinition = new ColumnDefinition();

                    JET_SESID sesid = database.IsamSession.Sesid;

                    // If we use the wide API (Vista+), then the temp table will be in UTF-16.
                    // Technically, this should have worked in Vista. But there was a bug, and
                    // it was fixed after Windows 7.
                    Encoding encodingOfTextColumns = EsentVersion.SupportsWindows8Features
                                                         ? Encoding.Unicode
                                                         : Encoding.ASCII;

                    string columnName = Api.RetrieveColumnAsString(
                        database.IsamSession.Sesid,
                        columnList.tableid,
                        columnList.columnidcolumnname,
                        encodingOfTextColumns);
                    JET_COLUMNBASE columnbase;
                    Api.JetGetColumnInfo(database.IsamSession.Sesid, database.Dbid, tableName, columnName, out columnbase);
                    columnDefinition.columnid = new Columnid(columnbase);
                    columnDefinition.name = columnDefinition.columnid.Name;
                    columnDefinition.type = columnDefinition.columnid.Type;

                    ColumndefGrbit grbitColumn = (ColumndefGrbit)Api.RetrieveColumnAsUInt32(sesid, columnList.tableid, columnList.columnidgrbit).GetValueOrDefault();
                    columnDefinition.flags = ColumnFlagsFromGrbits(grbitColumn);

                    columnDefinition.maxLength = Api.RetrieveColumnAsInt32(sesid, columnList.tableid, columnList.columnidcbMax).GetValueOrDefault();

                    columnDefinition.IsAscii = columnbase.cp == JET_CP.ASCII;
                    byte[] defaultValueBytes = Api.RetrieveColumn(sesid, columnList.tableid, columnList.columnidDefault);

                    Columnid isamColumnid = columnDefinition.columnid;
                    columnDefinition.defaultValue = Converter.ObjectFromBytes(
                        isamColumnid.Coltyp,
                        columnDefinition.IsAscii,
                        defaultValueBytes);

                    columnDefinition.ReadOnly = true;

                    return columnDefinition;
                }
            }
        }
Beispiel #28
0
 /// <summary>
 /// Initializes a new instance of the <see cref="TableCollection"/> class.
 /// </summary>
 /// <param name="database">The database.</param>
 internal TableCollection(IsamDatabase database)
 {
     this.database = database;
     this.readOnly = true;
 }
Beispiel #29
0
        /// <summary>
        /// Creates a <see cref="ColumnDefinition"/> object representing the column passed in by <paramref name="columnBase"/>.
        /// </summary>
        /// <param name="database">The database.</param>
        /// <param name="tableName">Name of the table.</param>
        /// <param name="columnBase">The <see cref="JET_COLUMNBASE"/> object that represents this particular column.</param>
        /// <returns>
        /// A <see cref="ColumnDefinition"/> object based on the <paramref name="columnBase"/> object.
        /// </returns>
        internal static ColumnDefinition Load(IsamDatabase database, string tableName, JET_COLUMNBASE columnBase)
        {
            lock (database.IsamSession)
            {
                using (IsamTransaction trx = new IsamTransaction(database.IsamSession))
                {
                    JET_SESID sesid = database.IsamSession.Sesid;

                    // load info for the column
                    ColumnDefinition columnDefinition = new ColumnDefinition();

                    columnDefinition.columnid = new Columnid(columnBase);
                    columnDefinition.name = columnDefinition.columnid.Name;
                    columnDefinition.type = columnDefinition.columnid.Type;

                    columnDefinition.flags = ColumnFlagsFromGrbits(columnBase.grbit);

                    columnDefinition.maxLength = (int)columnBase.cbMax;
                    columnDefinition.IsAscii = columnBase.cp == JET_CP.ASCII;

                    // there is currently no efficient means to retrieve the
                    // default value of a specific column from JET.  so, we are
                    // going to reach into the catalog and fetch it directly
                    JET_TABLEID tableidCatalog;
                    Api.JetOpenTable(
                        sesid,
                        database.Dbid,
                        "MSysObjects",
                        null,
                        0,
                        OpenTableGrbit.ReadOnly,
                        out tableidCatalog);

                    Api.JetSetCurrentIndex(sesid, tableidCatalog, "RootObjects");
                    Api.MakeKey(sesid, tableidCatalog, true, MakeKeyGrbit.NewKey);
                    Api.MakeKey(
                        sesid,
                        tableidCatalog,
                        Converter.BytesFromObject(JET_coltyp.Text, true, columnBase.szBaseTableName),
                        MakeKeyGrbit.None);
                    Api.JetSeek(sesid, tableidCatalog, SeekGrbit.SeekEQ);
                    JET_COLUMNBASE columnbaseCatalog;
                    Api.JetGetTableColumnInfo(sesid, tableidCatalog, "ObjidTable", out columnbaseCatalog);
                    uint objidTable = Api.RetrieveColumnAsUInt32(sesid, tableidCatalog, columnbaseCatalog.columnid).GetValueOrDefault();

                    Api.JetSetCurrentIndex(sesid, tableidCatalog, "Name");
                    Api.MakeKey(sesid, tableidCatalog, objidTable, MakeKeyGrbit.NewKey);
                    Api.MakeKey(sesid, tableidCatalog, (short)2, MakeKeyGrbit.None);
                    Api.MakeKey(sesid, tableidCatalog, columnBase.szBaseColumnName, Encoding.ASCII, MakeKeyGrbit.None);
                    Api.JetSeek(sesid, tableidCatalog, SeekGrbit.SeekEQ);

                    Api.JetGetTableColumnInfo(sesid, tableidCatalog, "DefaultValue", out columnbaseCatalog);
                    byte[] defaultValueBytes = Api.RetrieveColumn(sesid, tableidCatalog, columnbaseCatalog.columnid);

                    Columnid isamColumnid = columnDefinition.columnid;
                    columnDefinition.defaultValue = Converter.ObjectFromBytes(
                        isamColumnid.Coltyp,
                        columnDefinition.IsAscii,
                        defaultValueBytes);

                    columnDefinition.ReadOnly = true;

                    return columnDefinition;
                }
            }
        }
Beispiel #30
0
 /// <summary>
 /// Initializes a new instance of the <see cref="ColumnEnumerator"/> class.
 /// </summary>
 /// <param name="enumerator">The enumerator.</param>
 internal ColumnEnumerator(IDictionaryEnumerator enumerator)
 {
     this.database   = null;
     this.enumerator = enumerator;
 }
Beispiel #31
0
        /// <summary>
        /// Creates an <see cref="IndexDefinition"/> object from the specified <paramref name="indexList"/>.
        /// </summary>
        /// <param name="database">The database.</param>
        /// <param name="tableName">Name of the table.</param>
        /// <param name="indexList">The index list.</param>
        /// <returns>An <see cref="IndexDefinition"/> object represting the specified index.</returns>
        internal static IndexDefinition Load(IsamDatabase database, string tableName, JET_INDEXLIST indexList)
        {
            lock (database.IsamSession)
            {
                JET_SESID sesid = database.IsamSession.Sesid;
                using (IsamTransaction trx = new IsamTransaction(database.IsamSession))
                {
                    // load info for the index
                    IndexDefinition indexDefinition = new IndexDefinition();

                    indexDefinition.name = Api.RetrieveColumnAsString(
                        sesid,
                        indexList.tableid,
                        indexList.columnidindexname);

                    CreateIndexGrbit grbitIndex = (CreateIndexGrbit)Api.RetrieveColumnAsUInt32(sesid, indexList.tableid, indexList.columnidgrbitIndex);
                    indexDefinition.flags = IndexFlagsFromGrbits(grbitIndex);

                    Api.JetGetIndexInfo(
                        sesid,
                        database.Dbid,
                        tableName,
                        indexDefinition.name,
                        out indexDefinition.density,
                        JET_IdxInfo.SpaceAlloc);
                    int lcid;
                    Api.JetGetIndexInfo(
                        database.IsamSession.Sesid,
                        database.Dbid,
                        tableName,
                        indexDefinition.name,
                        out lcid,
                        JET_IdxInfo.LCID);
                    indexDefinition.cultureInfo = new CultureInfo(lcid);

                    indexDefinition.compareOptions =
                        Conversions.CompareOptionsFromLCMapFlags(
                            Api.RetrieveColumnAsUInt32(
                                database.IsamSession.Sesid,
                                indexList.tableid,
                                indexList.columnidLCMapFlags).GetValueOrDefault());

                    // CONSIDER:  move this workaround into Isam.Interop
                    try
                    {
                        ushort maxKeyLength;
                        Api.JetGetIndexInfo(
                            database.IsamSession.Sesid,
                            database.Dbid,
                            tableName,
                            indexDefinition.name,
                            out maxKeyLength,
                            JET_IdxInfo.KeyMost);
                        indexDefinition.maxKeyLength = maxKeyLength;
                    }
                    catch (EsentInvalidParameterException)
                    {
                        indexDefinition.maxKeyLength = 255;
                    }
                    catch (EsentColumnNotFoundException)
                    {
                        indexDefinition.maxKeyLength = 255;
                    }

                    // load info for each key column in the index
                    int currentColumn = 0;
                    int totalNumberColumns = Api.RetrieveColumnAsInt32(sesid, indexList.tableid, indexList.columnidcColumn).GetValueOrDefault();

                    indexDefinition.keyColumnCollection = new KeyColumnCollection();
                    do
                    {
                        // load info for this key column
                        IndexKeyGrbit grbitColumn = (IndexKeyGrbit)Api.RetrieveColumnAsUInt32(sesid, indexList.tableid, indexList.columnidgrbitColumn);
                        bool isAscending = (grbitColumn & IndexKeyGrbit.Descending) == 0;
                        string columnName = Api.RetrieveColumnAsString(
                            sesid,
                            indexList.tableid,
                            indexList.columnidcolumnname);
                        JET_COLUMNBASE columnbase;
                        Api.JetGetColumnInfo(sesid, database.Dbid, tableName, columnName, out columnbase);

                        indexDefinition.keyColumnCollection.Add(new KeyColumn(new Columnid(columnbase), isAscending));

                        // move onto the next key column definition, unless it is
                        // the last key column
                        if (currentColumn != totalNumberColumns - 1)
                        {
                            Api.TryMoveNext(sesid, indexList.tableid);
                        }
                    }
                    while (++currentColumn < totalNumberColumns);

                    indexDefinition.keyColumnCollection.ReadOnly = true;

                    // Vista: There is currently no efficient means to retrieve the
                    // conditional columns for an index from JET.  so, we are
                    // going to reach into the catalog and fetch them directly.
                    //
                    // FUTURE: Windows 7 introduced Windows7IdxInfo.CreateIndex and Windows7IdxInfo.CreateIndex2 (and
                    // Win8 has Windows8IdxInfo.CreateIndex3). Consider retrieving the conditional columns with that
                    // API and converting the results. But that does not solve the problem for Vista.
                    indexDefinition.conditionalColumnCollection = new ConditionalColumnCollection();
                    JET_TABLEID tableidCatalog;
                    Api.JetOpenTable(
                        database.IsamSession.Sesid,
                        database.Dbid,
                        "MSysObjects",
                        null,
                        0,
                        OpenTableGrbit.ReadOnly,
                        out tableidCatalog);

                    Api.JetSetCurrentIndex(sesid, tableidCatalog, "RootObjects");

                    Api.MakeKey(sesid, tableidCatalog, true, MakeKeyGrbit.NewKey);
                    Api.MakeKey(sesid, tableidCatalog, tableName, Encoding.ASCII, MakeKeyGrbit.None);
                    Api.JetSeek(sesid, tableidCatalog, SeekGrbit.SeekEQ);

                    JET_COLUMNID columnidTemp = Api.GetTableColumnid(sesid, tableidCatalog, "ObjidTable");
                    int objidTable = Api.RetrieveColumnAsInt32(sesid, tableidCatalog, columnidTemp).GetValueOrDefault();

                    Api.JetSetCurrentIndex(sesid, tableidCatalog, "Name");
                    Api.MakeKey(sesid, tableidCatalog, objidTable, MakeKeyGrbit.NewKey);
                    Api.MakeKey(sesid, tableidCatalog, (short)3, MakeKeyGrbit.None);
                    Api.MakeKey(sesid, tableidCatalog, indexDefinition.name, Encoding.ASCII, MakeKeyGrbit.None);
                    Api.JetSeek(sesid, tableidCatalog, SeekGrbit.SeekEQ);

                    columnidTemp = Api.GetTableColumnid(sesid, tableidCatalog, "Flags");
                    int indexFlagsBytes = Api.RetrieveColumnAsInt32(sesid, tableidCatalog, columnidTemp).GetValueOrDefault();

                    columnidTemp = Api.GetTableColumnid(sesid, tableidCatalog, "ConditionalColumns");
                    byte[] conditionalColumnsBytes = Api.RetrieveColumn(sesid, tableidCatalog, columnidTemp);

                    for (int ib = 0; conditionalColumnsBytes != null && ib < conditionalColumnsBytes.Length; ib += 4)
                    {
                        uint colid;
                        bool mustBeNull;
                        JET_COLUMNBASE columnBase;

                        // fIDXExtendedColumns
                        if ((indexFlagsBytes & 0xffff0000) == 0x00010000)
                        {
                            // fIDXSEGTemplateColumn
                            if ((conditionalColumnsBytes[ib + 0] & 0x80) != 0)
                            {
                                // fCOLUMNIDTemplate
                                colid = 0x80000000 | (uint)(conditionalColumnsBytes[ib + 3] << 8) | (uint)conditionalColumnsBytes[ib + 2];
                            }
                            else
                            {
                                colid = (uint)(conditionalColumnsBytes[ib + 3] << 8) | (uint)conditionalColumnsBytes[ib + 2];
                            }

                            // fIDXSEGMustBeNull
                            if ((conditionalColumnsBytes[ib + 0] & 0x20) != 0)
                            {
                                mustBeNull = true;
                            }
                            else
                            {
                                mustBeNull = false;
                            }
                        }
                        else
                        {
                            // do not load conditional columns from an unknown format
                            continue;
                        }

                        JET_COLUMNID castedColid = JET_COLUMNID.CreateColumnidFromNativeValue(unchecked((int)colid));
                        VistaApi.JetGetColumnInfo(
                            database.IsamSession.Sesid,
                            database.Dbid,
                            tableName,
                            castedColid,
                            out columnBase);

                        indexDefinition.conditionalColumnCollection.Add(new ConditionalColumn(new Columnid(columnBase), mustBeNull));
                    }

                    indexDefinition.conditionalColumnCollection.ReadOnly = true;

                    indexDefinition.ReadOnly = true;

                    return indexDefinition;
                }
            }
        }