/// <summary>
        /// This method is used to lock a specified range of bytes in a Stream object.
        /// </summary>
        /// <param name="preState">Specifies the pre-state before call [RopLockRegionStream]</param>
        /// <param name="error">Return error
        /// 1. If there are previous locks that are not expired, the server MUST return an AccessDenied error.
        /// 2. If a session with an expired lock calls any ROP for this Stream object that would encounter the locked region, 
        /// the server MUST return a NetworkError.</param>
        public void RopLockRegionStreamMethod(PreStateBeforeLock preState, out CPRPTErrorCode error)
        {
            error = CPRPTErrorCode.None;
            RopLockRegionStreamResponse lockRegionStreamResponse;

            // The regionOffset value used in RopLockRegionStream.
            ulong regionOffset = 0;

            // The lockFlags value used in RopLockRegionStream.
            uint lockFlags = (uint)LockFlags.OtherValue;
            RopGetStreamSizeResponse getStreamSizeRes = this.RopGetStreamSize(this.cprptCurrentHandle, true);
            ulong regionSize = getStreamSizeRes.StreamSize;

            lockRegionStreamResponse = this.RopLockRegionStream(this.cprptCurrentHandle, regionOffset, regionSize, lockFlags, false);

            if (preState == PreStateBeforeLock.PreLockNotExpired)
            {
                error = (CPRPTErrorCode)lockRegionStreamResponse.ReturnValue;
                this.Site.Assert.AreEqual(CPRPTErrorCode.None, error, string.Format("RopLockRegionStream failed with error: 0x{0:X8}", lockRegionStreamResponse.ReturnValue));

                lockRegionStreamResponse = this.RopLockRegionStream(this.cprptCurrentHandle, regionOffset, regionSize, lockFlags, false);
                error = (CPRPTErrorCode)lockRegionStreamResponse.ReturnValue;
            }
            else if (preState == PreStateBeforeLock.WithExpiredLock)
            {
                // The byteCount variable in RopReadStream.
                ushort byteCount = 1;

                // The maxByteCount Variable in RopReadStream.
                uint maxByteCount = 1;
                this.RopReadStream(this.cprptCurrentHandle, byteCount, maxByteCount, false);
                error = (CPRPTErrorCode)lockRegionStreamResponse.ReturnValue;

                this.Site.Assert.AreNotEqual(CPRPTErrorCode.AccessDenied, error, string.Format("RopLockRegionStream failed with error: 0x{0:X8}", lockRegionStreamResponse.ReturnValue));
            }
            else if (preState == PreStateBeforeLock.Normal)
            {
                error = (CPRPTErrorCode)lockRegionStreamResponse.ReturnValue;

                this.Site.Assert.AreEqual((uint)CPRPTErrorCode.None, lockRegionStreamResponse.ReturnValue, string.Format("RopLockRegionStream failed with error: 0x{0:X8}", lockRegionStreamResponse.ReturnValue));
            }

            this.VerifyRopLockRegionStream(lockRegionStreamResponse);
        }
        /// <summary>
        /// This method is used to open a different type of properties as a Stream object, enabling the client to perform various streaming operations on the property. 
        /// </summary>
        /// <param name="obj">Specifies which object will be operated.</param>
        /// <param name="propertyType">Specifies which type of property will be operated.</param>
        /// <param name="error">Returned error code.</param>
        public void RopOpenStreamWithDifferentPropertyType(ObjectToOperate obj, PropertyTypeName propertyType, out CPRPTErrorCode error)
        {
            #region Initialize properties and parameter
            error = CPRPTErrorCode.None;
            TaggedPropertyValue propertyTag = this.GetTaggedPropertyTag(obj);

            uint handle = 0;
            switch (this.cprptCurrentType)
            {
                case ServerObjectType.Folder:
                    int index = obj == ObjectToOperate.FifthObject ? (int)ObjectToOperate.FirstObject : (int)obj;
                    handle = cprptFolderHandle[index];
                    break;
                case ServerObjectType.Message:
                    handle = cprptMessageHandle[(int)obj];
                    break;
                case ServerObjectType.Attachment:
                    handle = cprptAttachmentHandle[(int)obj];
                    break;
                default:
                    break;
            }

            byte openModeFlags = ConstValues.OpenModeFlagsCreate;
            propertyTag.PropertyTag.PropertyType = (ushort)propertyType;

            if (this.cprptCurrentType != ServerObjectType.Folder)
            {
                propertyTag.PropertyTag.PropertyId++;
            }
            else
            {
                if (obj == ObjectToOperate.FifthObject)
                {
                    switch (propertyType)
                    {
                        case PropertyTypeName.PtypBinary:
                            propertyTag.PropertyTag.PropertyId = 0x0e09;
                            propertyTag.PropertyTag.PropertyType = 0x0102;
                            break;
                        case PropertyTypeName.PtypString:
                            propertyTag.PropertyTag.PropertyId = 0x3001;
                            propertyTag.PropertyTag.PropertyType = 0x001f;
                            break;
                        default:
                            break;
                    }

                    openModeFlags = ConstValues.OpenModeFlagsReadOnly;
                }
                else
                {
                    // Set PTagRulesData property for Folder object
                    propertyTag.PropertyTag.PropertyId = ushort.Parse(Common.GetConfigurationPropertyValue("FolderPropertyID2", this.Site));
                }
            }

            error = CPRPTErrorCode.Other;

            #endregion
            RopOpenStreamResponse openStreamResponse;
            uint openHandle = this.RopOpenStream(handle, out openStreamResponse, propertyTag.PropertyTag, openModeFlags, false);

            error = (CPRPTErrorCode)openStreamResponse.ReturnValue;

            #region Write stream to verify having write permission
            if (this.cprptCurrentType == ServerObjectType.Message)
            {
                RopWriteStreamResponse writeStreamResponse = this.RopWriteStream(openHandle, WriteData, false);
                this.RopCommitStream(openHandle, false);

                this.VerifyRopWriteStreamWithCreatePermission(writeStreamResponse);
            }
            #endregion
        }
        /// <summary>
        /// This method is used to set the seek pointer to a new location, which is relative to the beginning of the stream, the end of the stream, or the location of the current seek pointer.
        /// </summary>
        /// <param name="condition">Specifies particular scenario of RopSeekStream.</param>
        /// <param name="isStreamExtended">Indicates whether a stream object is extended and zero filled to the new seek location.</param>
        /// <param name="error">Returned error code.</param>
        public void RopSeekStreamMethod(SeekStreamCondition condition, out bool isStreamExtended, out CPRPTErrorCode error)
        {
            error = CPRPTErrorCode.None;
            isStreamExtended = false;
            RopGetStreamSizeResponse sizeRes = this.RopGetStreamSize(this.cprptCurrentHandle, true);
            uint size = sizeRes.StreamSize;

            // The origin value in RopSeekStreamMethod.
            byte origin = (byte)Origin.Beginning;

            // The offset value in RopSeekStreamMethod.
            long offset = 0;
            switch (condition)
            {
                case SeekStreamCondition.MovedBeyondMaxStreamSize:
                    origin = (byte)Origin.Beginning;

                    // The maximum value of unit is larger than 2^31 bytes.
                    offset = uint.MaxValue;
                    break;
                case SeekStreamCondition.MovedBeyondEndOfStream:
                    origin = (byte)Origin.End;
                    offset++;
                    break;
                case SeekStreamCondition.Normal:
                    break;
                case SeekStreamCondition.OriginInvalid:
                    origin = (byte)Origin.Invalid;
                    break;
                default:
                    break;
            }

            RopSeekStreamResponse seekStreamResponse = this.RopSeekStream(this.cprptCurrentHandle, origin, offset, false);
            error = (CPRPTErrorCode)seekStreamResponse.ReturnValue;
            if (error != CPRPTErrorCode.StreamSeekError)
            {
                if (condition == SeekStreamCondition.MovedBeyondEndOfStream)
                {
                    this.RopWriteStream(this.cprptCurrentHandle, WriteData, true);
                }

                sizeRes = this.RopGetStreamSize(this.cprptCurrentHandle, true);
                if (size < sizeRes.StreamSize)
                {
                    isStreamExtended = true;
                }
            }

            this.VerifyRopSeekStream(seekStreamResponse, condition);
        }
예제 #4
0
        public static void RopCopyToStreamMethod(bool isDestinationExist, out bool isReadWriteSuccess, out CPRPTErrorCode error)
        {
            Condition.IsTrue(isInitialized && isStreamOpenedSuccess);
            Condition.IsTrue(isFirstObjectGot && isSecondObjectGot);

            if (isDestinationExist)
            {
                isReadWriteSuccess = true;
                error = CPRPTErrorCode.None;

                if (requirementContainer[867091])
                {
                    ModelHelper.CaptureRequirement(
                        867091,
                        @"[In Appendix A: Product Behavior] Implementation does implement the RopCopyToStream ROP. (<13> Section 3.2.5.18: Exchange 2007 and above products (except the initial release version of Exchange 2010) follow this behavior.)");
                }
                
                ModelHelper.CaptureRequirement(
                    592,
                    @"[In Processing RopCopyToStream] The server MUST read the number of bytes requested from the source Stream object and write those bytes into the destination Stream object.");
            }
            else
            {
                isReadWriteSuccess = false;
                error = CPRPTErrorCode.NullDestinationObject;
            }

            isStreamWriteSuccess = false;
        }
        /// <summary>
        /// This method is used to open a property as a Stream object, enabling the client to perform various streaming operations on the property. 
        /// </summary>
        /// <param name="obj">Specifies which object will be operated.</param>
        /// <param name="openFlag">Specifies OpenModeFlags for [RopOpenStream].</param>
        /// <param name="isPropertyTagExist">Indicates whether request property exist.</param>
        /// <param name="isStreamSizeEqualToStream">Indicates whether StreamSize in response is 
        /// the same with the current number of BYTES in the stream.</param>
        /// <param name="error">If the property tag does not exist for the object and "Create" 
        /// is not specified in OpenModeFlags, NotFound error should be returned.</param>
        public void RopOpenStreamMethod(ObjectToOperate obj, OpenModeFlags openFlag, bool isPropertyTagExist, out bool isStreamSizeEqualToStream, out CPRPTErrorCode error)
        {
            #region Initialize properties and parameter
            error = CPRPTErrorCode.None;
            isStreamSizeEqualToStream = false;
            TaggedPropertyValue propertyTag = this.GetTaggedPropertyTag(obj);

            uint handle = 0;
            switch (this.cprptCurrentType)
            {
                case ServerObjectType.Folder:
                    handle = cprptFolderHandle[(int)obj];

                    // For folder object, open PTagRulesData property
                    propertyTag = this.GetTaggedPropertyTag(ObjectToOperate.ThirdObject);
                    break;
                case ServerObjectType.Message:
                    handle = cprptMessageHandle[(int)obj];
                    break;
                case ServerObjectType.Attachment:
                    handle = cprptAttachmentHandle[(int)obj];
                    break;
                default:
                    Site.Assert.Fail("Invalid server object type {0} for RopOpenStream method.", this.cprptCurrentType);
                    break;
            }

            byte openModeFlags = ConstValues.OpenModeFlagsReadOnly;
            switch (openFlag)
            {
                case OpenModeFlags.ReadOnly:
                    openModeFlags = ConstValues.OpenModeFlagsReadOnly;
                    break;
                case OpenModeFlags.ReadWrite:
                    openModeFlags = ConstValues.OpenModeFlagsReadWrite;
                    break;
                case OpenModeFlags.Create:
                    openModeFlags = ConstValues.OpenModeFlagsCreate;
                    break;
                case OpenModeFlags.BestAccess:
                    openModeFlags = ConstValues.OpenModeFlagsBestAccess;
                    break;
                default:
                    this.Site.Assert.Fail("Invalid OpenModeFlags enum value {0}.", openFlag);
                    break;
            }

            if (isPropertyTagExist)
            {
                #region Get original stream value of current property tag
                string objKey;
                switch (this.cprptCurrentType)
                {
                    case ServerObjectType.Folder:
                        if (obj == ObjectToOperate.FirstObject)
                        {
                            objKey = "Folder1";
                        }
                        else
                        {
                            objKey = "Folder2";
                        }

                        break;
                    case ServerObjectType.Message:
                        if (obj == ObjectToOperate.FirstObject)
                        {
                            objKey = "Message1";
                        }
                        else
                        {
                            objKey = "Message2";
                        }

                        break;
                    case ServerObjectType.Attachment:
                        if (obj == ObjectToOperate.FirstObject)
                        {
                            objKey = "Attachment1";
                        }
                        else
                        {
                            objKey = "Attachment2";
                        }

                        break;
                    default:
                        objKey = string.Empty;
                        break;
                }

                bool isPropertyFound;
                byte[] originalStreamValue = this.Session2ReadStream(objKey, propertyTag.PropertyTag, out isPropertyFound);

                // Store the value for further verification
                TaggedPropertyValue tagPropertyValue = new TaggedPropertyValue
                {
                    PropertyTag = propertyTag.PropertyTag,
                    Value = originalStreamValue
                };

                if (this.tagPropertyValuesToVerification.ContainsKey(objKey))
                {
                    this.tagPropertyValuesToVerification[objKey] = tagPropertyValue;
                }
                else
                {
                    this.tagPropertyValuesToVerification.Add(objKey, tagPropertyValue);
                }
                #endregion
            }
            else
            {
                propertyTag.PropertyTag.PropertyId = NewCreatePropertyID;
                propertyTag.PropertyTag.PropertyType = (ushort)PropertyTypeName.PtypBinary;
            }

            error = CPRPTErrorCode.None;
            isStreamSizeEqualToStream = false;
            #endregion

            RopOpenStreamResponse openStreamResponse;
            uint openHandle = this.RopOpenStream(handle, out openStreamResponse, propertyTag.PropertyTag, openModeFlags, false);

            this.VerifyRopOpenStream(openStreamResponse, this.cprptCurrentType, isPropertyTagExist, openFlag);

            #region Verify error, isStreamSizeEqualToStream and set handle
            if (openFlag != OpenModeFlags.Create && isPropertyTagExist == false && openStreamResponse.ReturnValue == (uint)CPRPTErrorCode.NotFound)
            {
                error = CPRPTErrorCode.NotFound;
            }
            else if (openStreamResponse.ReturnValue == (uint)CPRPTErrorCode.None)
            {
                error = CPRPTErrorCode.None;
                uint streamSize = openStreamResponse.StreamSize;
                switch (obj)
                {
                    case ObjectToOperate.FirstObject:
                        this.cprptCurrentHandle = this.cprptFirstHandle = openHandle;
                        break;
                    case ObjectToOperate.SecondObject:
                        this.cprptSecondHandle = openHandle;
                        break;
                    default:
                        break;
                }

                RopSeekStreamResponse res = this.RopSeekStream(openHandle, (byte)Origin.End, ConstValues.RopSeekStreamOffsetZero, false);
                if (res.ReturnValue == (uint)CPRPTErrorCode.None)
                {
                    if (streamSize == res.NewPosition)
                    {
                        isStreamSizeEqualToStream = true;
                    }
                }
            }
            #endregion
        }
        /// <summary>
        /// This method is used to write bytes to a stream and commits the stream. 
        /// </summary>
        /// <param name="error">This ROP MUST NOT be used on Stream objects opened on 
        /// properties on Folder objects which means it should be failed against Folder object.</param>
        public void RopWriteAndCommitStreamMethod(out CPRPTErrorCode error)
        {
            error = CPRPTErrorCode.None;
            bool isWriteCorrectDataToStream = false;
            RopSeekStreamResponse seekStreamResponse1 = this.RopSeekStream(this.cprptCurrentHandle, (byte)Origin.Current, 0, true);
            RopWriteStreamResponse writeStreamResponse = this.RopWriteAndCommitStream(this.cprptCurrentHandle, WriteData, false);
            RopSeekStreamResponse seekStreamResponse2 = this.RopSeekStream(this.cprptCurrentHandle, (byte)Origin.Current, 0, true);

            if (seekStreamResponse2.NewPosition - seekStreamResponse1.NewPosition == (ulong)WriteData.Length)
            {
                isWriteCorrectDataToStream = true;
            }

            // Message and attachment object can only be changed after saving.
            this.RopSaveChangesAttachment(cprptAttachmentHandle[0], true);
            this.RopSaveChangesMessage(cprptMessageHandle[0], true);

            this.VerifyRopWriteAndCommitStream(writeStreamResponse, isWriteCorrectDataToStream);

            if (this.cprptCurrentType == ServerObjectType.Folder && writeStreamResponse.ReturnValue != (uint)CPRPTErrorCode.None)
            {
                error = CPRPTErrorCode.NotFound;
            }
        }
        /// <summary>
        /// This method is used to copy or move all but a specified few properties from a source object to a destination object. 
        /// </summary>
        /// <param name="copyFlag">Specifies the CopyFlags in the call request.</param>
        /// <param name="isWantAsynchronousZero">Indicates whether WantAsynchronous parameter in call request is zero.</param>
        /// <param name="isWantSubObjectsZero">Indicates whether WantSubObjects parameter in call request is zero.</param>
        /// <param name="isDestinationExist">Indicates whether destination object is exist for [RopCopyTo].</param>
        /// <param name="isPropertiesDeleted">If CopyFlags is set to Move,Source object will be deleted after copy to.</param>
        /// <param name="isSubObjectCopied">Indicates whether sub-object properties is also be copied.</param>
        /// <param name="isOverwriteDestination">If CopyFlags is set to NoOverWrite,Destination should not be overwritten.</param>
        /// <param name="isReturnedRopProgress">If this ROP is performed Asynchronously,RopProgress response
        /// returned instead of RopCopyProperties response.</param>
        /// <param name="isChangedInDB">Indicates whether destination is changed in database.</param>
        /// <param name="error">If destination object is not exist,NullDestinationObject error will be returned.</param>
        public void RopCopyToMethod(
            CopyFlags copyFlag,
            bool isWantAsynchronousZero,
            bool isWantSubObjectsZero,
            bool isDestinationExist,
            out bool isPropertiesDeleted,
            out bool isSubObjectCopied,
            out bool isOverwriteDestination,
            out bool isReturnedRopProgress,
            out bool isChangedInDB,
            out CPRPTErrorCode error)
        {
            // Check if there are conflict SHOULD/MAY settings 
            this.CheckRequirementConflict(86702, 18402);
            this.CheckRequirementConflict(86708, 5070506);

            #region Set parameters
            isPropertiesDeleted = false;
            isSubObjectCopied = false;
            isOverwriteDestination = false;
            isReturnedRopProgress = false;
            isChangedInDB = false;
            error = CPRPTErrorCode.None;

            uint secondHandle = InvalidHandle;
            if (isDestinationExist)
            {
                secondHandle = this.cprptSecondHandle;
                if (this.cprptCurrentType == ServerObjectType.Folder)
                {
                    RopCreateFolderResponse createFolderResponse;
                    string displayName = SubFolder;
                    secondHandle = this.RopCreateFolder(secondHandle, out createFolderResponse, displayName, "Comment: " + displayName, true);
                }
            }

            byte copyFlags = (byte)RopCopyToCopyFlags.None;

            switch (copyFlag)
            {
                case CopyFlags.None:
                    copyFlags = (byte)RopCopyToCopyFlags.None;
                    break;
                case CopyFlags.Move:
                    copyFlags = (byte)RopCopyToCopyFlags.Move;
                    break;
                case CopyFlags.NoOverWrite:
                    copyFlags = (byte)RopCopyToCopyFlags.NoOverwrite;
                    break;
                case CopyFlags.MoveAndNoOverWrite:
                    copyFlags = (byte)RopCopyPropertiesCopyFlags.MoveAndOverwrite;
                    break;
                default:
                    copyFlags = (byte)0x05;
                    break;
            }

            // The value indicates whether the ROP is to be processed synchronously or asynchronously, 0 means synchronous operation. 
            byte wantAsynchronous = 0;

            byte wantSubObjects = 1;
            if (isWantSubObjectsZero)
            {
                wantSubObjects = 0;
            }

            PropertyTag[] propertyTags = new PropertyTag[1];
            propertyTags[0] = this.GetTaggedPropertyTag(ObjectToOperate.FirstObject).PropertyTag;
            #endregion

            #region Set the first handle property
            TaggedPropertyValue[] tagPropertyValue = new TaggedPropertyValue[2];
            tagPropertyValue[0] = this.GetTaggedPropertyTag(ObjectToOperate.FirstObject);
            tagPropertyValue[0].Value = Common.AddInt16LengthBeforeBinaryArray(tagPropertyValue[0].Value);
            tagPropertyValue[1] = this.GetTaggedPropertyTag(ObjectToOperate.SecondObject);
            tagPropertyValue[1].Value = Common.AddInt16LengthBeforeBinaryArray(tagPropertyValue[1].Value);

            this.RopSetProperties(this.cprptFirstHandle, tagPropertyValue, true);
            if (this.cprptCurrentType == ServerObjectType.Message)
            {
                this.RopSaveChangesMessage(this.cprptFirstHandle, true);
            }
            else if (this.cprptCurrentType == ServerObjectType.Attachment)
            {
                this.RopSaveChangesAttachment(this.cprptFirstHandle, true);
                this.RopSaveChangesMessage(cprptMessageHandle[0], true);
            }
            #endregion

            #region Set the second handle property
            TaggedPropertyValue[] tagPropertyValue1 = new TaggedPropertyValue[2];
            tagPropertyValue1[0] = this.GetTaggedPropertyTag(ObjectToOperate.FirstObject);
            tagPropertyValue1[0].Value[0] = (byte)(tagPropertyValue1[0].Value[0] + 1);
            tagPropertyValue1[0].Value = Common.AddInt16LengthBeforeBinaryArray(tagPropertyValue1[0].Value);
            tagPropertyValue1[1] = this.GetTaggedPropertyTag(ObjectToOperate.SecondObject);
            tagPropertyValue1[1].Value[0] = (byte)(tagPropertyValue1[1].Value[0] + 1);
            tagPropertyValue1[1].Value = Common.AddInt16LengthBeforeBinaryArray(tagPropertyValue1[1].Value);
            if (isDestinationExist)
            {
                this.RopSetProperties(secondHandle, tagPropertyValue1, true);
                if (this.cprptCurrentType == ServerObjectType.Message)
                {
                    this.RopSaveChangesMessage(secondHandle, true);
                }
                else if (this.cprptCurrentType == ServerObjectType.Attachment)
                {
                    this.RopSaveChangesAttachment(secondHandle, true);
                    this.RopSaveChangesMessage(cprptMessageHandle[0], true);
                }

                // Store the TaggedPropertyValue for further verification
                this.tagPropertyValuesToVerification.Clear();
                switch (this.cprptCurrentType)
                {
                    case ServerObjectType.Folder:
                        this.tagPropertyValuesToVerification.Add(ConstValues.ServerObjectTypeFolderKey, tagPropertyValue1[0]);
                        break;
                    case ServerObjectType.Message:
                        this.tagPropertyValuesToVerification.Add(ConstValues.ServerObjectTypeMessageKey, tagPropertyValue1[0]);
                        break;
                    case ServerObjectType.Attachment:
                        this.tagPropertyValuesToVerification.Add(ConstValues.ServerObjectTypeAttachmentKey, tagPropertyValue1[0]);
                        break;
                    default:
                        break;
                }
            }
            #endregion

            if (!isWantAsynchronousZero)
            {
                wantAsynchronous = 1;
                if (copyFlag != CopyFlags.NoOverWrite && this.cprptCurrentType == ServerObjectType.Folder && !isWantSubObjectsZero)
                {
                    RopCreateMessageResponse createMessageResponse;
                    uint msgHandle = this.RopCreateMessage(cprptFolderHandle[0], cprptFolderId[0], ConstValues.RopCreateMessageAssociatedFlagNone, out createMessageResponse, true);
                    this.RopSaveChangesMessage(msgHandle, true);
                    this.RopRelease(msgHandle);
                }
            }

            // The property set in previous step should exist.
            TaggedPropertyValue existingValue = this.SearchProperty(this.cprptFirstHandle, tagPropertyValue[0].PropertyTag.PropertyId);
            Site.Assert.IsNotNull(existingValue, "The target property should not be null.");

            bool isExcluedPropertyCopied = true;
            PropertyTag[] propertyTag = new PropertyTag[1];
            propertyTag[0] = tagPropertyValue1[1].PropertyTag;
            object responseObj = this.RopCopyTo(this.cprptFirstHandle, secondHandle, (byte)HandleIndex.FirstIndex, (byte)HandleIndex.SecondIndex, wantAsynchronous, wantSubObjects, copyFlags, propertyTag);

            if (isDestinationExist)
            {
                RopGetPropertiesSpecificResponse getPropertiesSpecificResponse = this.RopGetPropertiesSpecific(secondHandle, 0, 0, propertyTag);
                if (!Common.CompareByteArray(getPropertiesSpecificResponse.RowData.PropertyValues[0].Value, tagPropertyValue[0].Value))
                {
                    isExcluedPropertyCopied = false;
                }

                this.VerifyRopCopyToExcludeElement(isExcluedPropertyCopied);
            }

            if (responseObj is RopProgressResponse)
            {
                isReturnedRopProgress = true;
            }
            else
            {
                RopCopyToResponse ropCopyToResponse = (RopCopyToResponse)responseObj;

                this.VerifyRopCopyTo(ropCopyToResponse, CopyToCondition.Normal, this.cprptCurrentType, copyFlag);

                error = (CPRPTErrorCode)ropCopyToResponse.ReturnValue;

                if (!isReturnedRopProgress && isWantAsynchronousZero && ropCopyToResponse.ReturnValue == (uint)RopResponseType.SuccessResponse)
                {
                    #region Check if the property is changed in DB
                    string objKey;
                    switch (this.cprptCurrentType)
                    {
                        case ServerObjectType.Folder:
                            objKey = "Folder2";
                            break;
                        case ServerObjectType.Message:
                            objKey = "Message2";
                            break;
                        case ServerObjectType.Attachment:
                            objKey = "Attachment2";
                            break;
                        default:
                            objKey = string.Empty;
                            break;
                    }

                    bool isPropertyFound;
                    byte[] propertyValueBeforeSave = this.Session2GetPropertyData(objKey, tagPropertyValue[0].PropertyTag, out isPropertyFound);

                    isChangedInDB = !Common.CompareByteArray(propertyValueBeforeSave, tagPropertyValue1[0].Value);
                    #endregion

                    #region Check if the value is overwritten
                    TaggedPropertyValue overwriteValue = this.SearchProperty(secondHandle, tagPropertyValue1[0].PropertyTag.PropertyId);
                    if (Common.CompareByteArray(overwriteValue.Value, tagPropertyValue1[0].Value))
                    {
                        isOverwriteDestination = false;
                    }
                    else
                    {
                        isOverwriteDestination = true;
                    }
                    #endregion

                    #region Check if the sub-object is copied
                    if (!isWantSubObjectsZero && isDestinationExist)
                    {
                        if (this.cprptCurrentType == ServerObjectType.Folder)
                        {
                            TaggedPropertyValue ptagValue = this.SearchProperty(secondHandle, (ushort)TaggedPropertyName.PidTagContentCount);
                            if (ptagValue.Value[0] != 0 || ptagValue.Value[1] != 0 || ptagValue.Value[2] != 0 || ptagValue.Value[3] != 0)
                            {
                                isSubObjectCopied = true;
                            }
                        }
                        else if (this.cprptCurrentType == ServerObjectType.Message)
                        {
                            RopOpenAttachmentResponse openAttRes;
                            this.RopOpenAttachment(secondHandle, cprptAttachmentId[0], out openAttRes, true);
                            if (openAttRes.ReturnValue == (uint)CPRPTErrorCode.None)
                            {
                                isSubObjectCopied = true;
                            }
                        }
                    }
                    #endregion

                    #region Check if the value is deleted
                    // The message and attachment objects must apply the changes to database
                    if (this.cprptCurrentType == ServerObjectType.Message)
                    {
                        this.RopSaveChangesMessage(this.cprptFirstHandle, true);
                    }
                    else if (this.cprptCurrentType == ServerObjectType.Attachment)
                    {
                        this.RopSaveChangesAttachment(this.cprptFirstHandle, false);
                        this.RopSaveChangesMessage(cprptMessageHandle[0], false);
                    }

                    switch (this.cprptCurrentType)
                    {
                        case ServerObjectType.Folder:
                            objKey = ConstValues.ServerObjectTypeFolderKey;
                            break;
                        case ServerObjectType.Message:
                            objKey = ConstValues.ServerObjectTypeMessageKey;
                            break;
                        case ServerObjectType.Attachment:
                            objKey = ConstValues.ServerObjectTypeAttachmentKey;
                            break;
                        default:
                            objKey = string.Empty;
                            break;
                    }

                    if (this.cprptCurrentType == ServerObjectType.Folder)
                    {
                        TaggedPropertyValue deleteValue = this.SearchProperty(this.cprptFirstHandle, tagPropertyValue[0].PropertyTag.PropertyId);
                        if (deleteValue == null)
                        {
                            isPropertiesDeleted = true;
                        }
                    }
                    else
                    {
                        if (this.cprptCurrentType == ServerObjectType.Attachment && copyFlag == CopyFlags.Move && Common.IsRequirementEnabled(86707, this.Site))
                        {
                            isPropertiesDeleted = true;
                        }
                        else
                        {
                            byte[] propertyValueNow = this.Session2GetPropertyData(objKey, tagPropertyValue[0].PropertyTag, out isPropertyFound);
                            if (!isPropertyFound)
                            {
                                isPropertiesDeleted = true;
                            }
                            else
                            {
                                byte[] expectedNotFoundError = new byte[] { 0x0f, 0x01, 0x04, 0x80 };
                                isPropertiesDeleted = Common.CompareByteArray(expectedNotFoundError, propertyValueNow);
                            }
                        }
                    }
                    #endregion
                }
            }
        }
예제 #8
0
        public static void RopOpenStreamMethod(
            ObjectToOperate objectToOperate,
            OpenModeFlags openFlag,
            bool isPropertyTagExist,
            out bool isStreamSizeEqualToStream,
            out CPRPTErrorCode error)
        {
            Condition.IsTrue(isInitialized);
            Condition.IsTrue(globalObj != ServerObjectType.Logon);

            // openFlag and error is designed for negative test case.
            error = CPRPTErrorCode.None;
            isStreamSizeEqualToStream = false;
            isStreamWriteSuccess = false;
            isStreamOpenedSuccess = true;

            streamOpenFlag = openFlag;
            ModelHelper.CaptureRequirement(
                885,
                @"[In Processing RopOpenStream] The server MUST open the stream in the mode indicated by the OpenModeFlags field as specified by the table in section 2.2.14.1.");

            if (isPropertyTagExist)
            {
                isStreamSizeEqualToStream = true;
            }
            else if (openFlag == OpenModeFlags.ReadOnly && isPropertyTagExist == false)
            {
                error = CPRPTErrorCode.NotFound;
                isStreamOpenedSuccess = false;
            }
        }
예제 #9
0
        public static void RopOpenStreamWithDifferentPropertyType(
            ObjectToOperate objectToOperate,
            PropertyTypeName propertyType,
            out CPRPTErrorCode error)
        {
            Condition.IsTrue(isInitialized);
            Condition.IsTrue(globalObj != ServerObjectType.Logon);
            Condition.IfThen(globalObj == ServerObjectType.Message || globalObj == ServerObjectType.Attachment, propertyType == PropertyTypeName.PtypBinary || propertyType == PropertyTypeName.PtypString || propertyType == PropertyTypeName.PtypObject);

            if (objectToOperate == ObjectToOperate.FirstObject)
            {
                Condition.IfThen(globalObj == ServerObjectType.Folder, propertyType == PropertyTypeName.PtypBinary);
            }
            else if (objectToOperate == ObjectToOperate.FifthObject)
            {
                Condition.IfThen(globalObj == ServerObjectType.Folder, propertyType == PropertyTypeName.PtypBinary || propertyType == PropertyTypeName.PtypString);
            }

            // openFlag and error is designed for negative test case.
            error = CPRPTErrorCode.None;            
            if (globalObj == ServerObjectType.Attachment && propertyType == PropertyTypeName.PtypBinary)
            {
                ModelHelper.CaptureRequirement(
                    25502,
                    @"[In RopOpenStream ROP] Single-valued PtypBinary type properties ([MS-OXCDATA] section 2.11.1) is supported for Attachment objects.");
            }

            if (globalObj == ServerObjectType.Attachment && propertyType == PropertyTypeName.PtypObject)
            {
                ModelHelper.CaptureRequirement(
                    25503,
                    @"[In RopOpenStream ROP] Single-valued PtypObject type properties ([MS-OXCDATA] section 2.11.1) is supported for Attachment objects.");
            }

            if (globalObj == ServerObjectType.Message && propertyType == PropertyTypeName.PtypBinary)
            {
                ModelHelper.CaptureRequirement(
                   25506,
                   @"[In RopOpenStream ROP] Single-valued PtypBinary type properties ([MS-OXCDATA] section 2.11.1) is supported for Message objects.");
            }

            if (globalObj == ServerObjectType.Message && propertyType == PropertyTypeName.PtypObject)
            {
                ModelHelper.CaptureRequirement(
                   25507,
                   @"[In RopOpenStream ROP] Single-valued PtypObject type properties ([MS-OXCDATA] section 2.11.1) is supported for Message objects.");
            }

            if (globalObj == ServerObjectType.Message && propertyType == PropertyTypeName.PtypString)
            {
                ModelHelper.CaptureRequirement(
                   25509,
                   @"[In RopOpenStream ROP] Single-valued PtypString type properties ([MS-OXCDATA] section 2.11.1) is supported for Message objects.");
            }

            if (globalObj == ServerObjectType.Attachment && propertyType == PropertyTypeName.PtypString)
            {
                if (requirementContainer[25505])
                {
                    ModelHelper.CaptureRequirement(
                        25505,
                        @"[In RopOpenStream ROP] Single-valued PtypString type properties ([MS-OXCDATA] section 2.11.1) is supported for Attachment objects.");
                }
                else
                {
                    error = CPRPTErrorCode.NotSupported;
                }            
            }
        }
예제 #10
0
 public static void SetCommonObjectProperties(CommonObjectProperty commonProperty, out CPRPTErrorCode error)
 {
     error = CPRPTErrorCode.None;
 }
예제 #11
0
        public static void RopGetPropertyIdsFromNamesMethod(
            bool isTestOrder,
            bool isCreateFlagSet,
            bool isPropertyNameExisting,
            SpecificPropertyName specialPropertyName,
            out bool isCreatedEntryReturned,
            out CPRPTErrorCode error)
        {
            Condition.IsTrue(isInitialized);

            isCreatedEntryReturned = false;
            error = CPRPTErrorCode.None;

            if (isCreateFlagSet && !isPropertyNameExisting)
            {
                isCreatedEntryReturned = true;
                ModelHelper.CaptureRequirement(
                    628,
                    @"[In RopGetPropertyIdsFromNames ROP Request Buffer] Flags: This field is set to 0x02 to request that a new entry be created for 
                    each named property that is not found in the existing mapping table; ");
            }

            if (!isCreateFlagSet)
            {
                isCreatedEntryReturned = false;
                ModelHelper.CaptureRequirement(
                    62801,
                    @"[In RopGetPropertyIdsFromNames ROP Request Buffer] Flags: This field is set to 0x00 otherwise[If not request a new entry to be created for each named property that is not found in the existing mapping table].");
            }
        }
예제 #12
0
        public static void RopCopyToMethodReturn(
            bool isPropertiesDeleted,
            bool isSubObjectCopied,
            bool isOverwriteDestination,
            bool isReturnedRopProgress,
            bool isChangedInDB,
            CPRPTErrorCode error)
        {
            Condition.IfThen(clientCopyFlag == CopyFlags.Move, error == CPRPTErrorCode.None);

            Condition.IsTrue(error == CPRPTErrorCode.None
                || error == CPRPTErrorCode.NullDestinationObject
                || error == CPRPTErrorCode.InvalidParameter);

            if (error == CPRPTErrorCode.None)
            {
                isCopyToSuccess = true;
            }

            // Test synchronous and asynchronous situation through "isClientWantAsynchronous", "isReturnedRopProgress" and "isWorkSynchronously"
            if (!isClientWantAsynchronous)
            {
                Condition.IsTrue(!isReturnedRopProgress);
                isWorkSynchronously = true;
                ModelHelper.CaptureRequirement(
                    177,
                    "[In RopCopyTo ROP Request Buffer] WantAsynchronous: If this field is set to zero, this ROP [RopCopyTo ROP] is processed synchronously. ");

                if (isDestinationInRequestExist)
                {
                    // To test the CopyFlags
                    if (clientCopyFlag == CopyFlags.NoOverWrite)
                    {
                        Condition.IsTrue(!isOverwriteDestination && !isPropertiesDeleted);
                        ModelHelper.CaptureRequirement(
                              5070504,
                              @"[In Processing RopCopyTo] If the NoOverwrite flag is set in the CopyFlags field, the server MUST NOT overwrite any properties that already have a value on the destination object. ");

                        ModelHelper.CaptureRequirement(
                              18501,
                              @"[In RopCopyTo ROP Request Buffer] CopyFlags: Move: otherwise(If this bit is not set to 0x01), properties are copied.");

                        ModelHelper.CaptureRequirement(
                            624,
                            @"[In RopCopyTo ROP Request Buffer] CopyFlags: NoOverwrite: If this bit[bit 0x02] is set, properties that already have a value on the destination object will not be overwritten;");

                        if (globalObj == ServerObjectType.Folder)
                        {
                            Condition.IsTrue(isChangedInDB);
                            ModelHelper.CaptureRequirement(
                                5070509,
                                @"[In Processing RopCopyTo] In the case of Folder objects, the changes on the source and destination MUST be immediately persisted.");
                        }

                        if (globalObj == ServerObjectType.Message)
                        {
                            Condition.IsFalse(isChangedInDB);

                            if (isClientWantSubObjects)
                            {
                                Condition.IsTrue(isSubObjectCopied);
                                ModelHelper.CaptureRequirement(
                                     181,
                                     "[In RopCopyTo ROP Request Buffer] WantSubObjects: If WantSubObjects is nonzero then sub-objects MUST also be copied.");
                            }
                            else
                            {
                                Condition.IsTrue(!isSubObjectCopied);
                                ModelHelper.CaptureRequirement(
                                    182,
                                    "[In RopCopyTo ROP Request Buffer] WantSubObjects: Otherwise[If WantSubObjects is zero] they[sub-objects] are  not[copied].");
                            }
                        }
                    }
                    else if (clientCopyFlag == CopyFlags.MoveAndNoOverWrite)
                    {
                        if (requirementContainer[86702])
                        {
                            Condition.IsTrue(error == CPRPTErrorCode.None);
                            ModelHelper.CaptureRequirement(
                               86702,
                               @"Implementation does support combination. (<3> Section 2.2.11.1: Exchange 2003 and Exchange 2007 support the combination of the Move bit and the NoOverwrite bit in the CopyFlags field.)");
                        }

                        if (requirementContainer[18402])
                        {
                            Condition.IsTrue(error == CPRPTErrorCode.InvalidParameter);
                            ModelHelper.CaptureRequirement(
                                18402,
                                @"[In RopCopyTo ROP Request Buffer] CopyFlags: Implementation doesn't support the combination of these bit(bit0x01 and bit 0x02) in CopyFlags.(Microsoft Exchange Server 2010 and above follow this behavior)");
                        }
                    }
                    else if (clientCopyFlag == CopyFlags.Move)
                    {
                        Condition.IsTrue(error == CPRPTErrorCode.None);
                        Condition.IsTrue(isOverwriteDestination);

                        ModelHelper.CaptureRequirement(
                            625,
                            @"[In RopCopyTo ROP Request Buffer] CopyFlags: otherwise[If this bit is not set to 0x02], they [properties that already have a value on the destination object] are overwritten.");

                        if (requirementContainer[86707])
                        {
                            ModelHelper.CaptureRequirement(
                                86707,
                                @"Implementation does delete the property. <8> Section 3.2.5.8: Exchange 2003, Exchange 2007, and Exchange 2010 delete the properties from the source object.)");
                        }
                    }
                    else if (clientCopyFlag == CopyFlags.Other)
                    {
                        if (requirementContainer[86708])
                        {
                            Condition.IsTrue(error == CPRPTErrorCode.None);
                            ModelHelper.CaptureRequirement(
                                86708,
                                @"Implementation does not return the InvalidParameter error code (0x80070057). <9> Section 3.2.5.8: Exchange 2003 and Exchange 2007 ignore invalid bits and do not return the InvalidParameter error code (0x80070057).");
                        }

                        if (requirementContainer[5070506])
                        {
                            Condition.IsTrue(error == CPRPTErrorCode.InvalidParameter);

                            ModelHelper.CaptureRequirement(
                                5070506,
                                @"[In Processing RopCopyTo] Implementation does return an InvalidParameter error (0x80070057). if any other bits are set in the CopyFlags field.(Microsoft Exchange Server 2010 and above follow this behavior.)");
                        }
                    }
                }
            }
            else
            {
                if (!isReturnedRopProgress)
                {
                    isWorkSynchronously = true;
                    ModelHelper.CaptureRequirement(
                        178,
                        @"[In RopCopyTo ROP Request Buffer] WantAsynchronou:] If this field is set to nonzero, this ROP [RopCopyTo ROP] is processed either synchronously or asynchronously.");

                    ModelHelper.CaptureRequirement(
                        50801,
                        @"[In Processing RopCopyTo] If the client requests asynchronous processing, the server can process this ROP asynchronously.");

                    ModelHelper.CaptureRequirement(
                       50802,
                       @"[In Processing RopCopyTo] During asynchronous processing, the server can indicate that the operation is still being processed by returning a RopProgress ROP response ([MS-OXCROPS] section 2.2.8.13), or it can indicate that the operation has already completed by returning a RopCopyTo ROP response. ");
                }
            }
        }
예제 #13
0
        public static void RopCopyPropertiesMethodReturn(
            bool isPropertiesDeleted,
            bool isChangedInDB,
            bool isOverwriteDestination,
            bool isReturnedRopProgress,
            CPRPTErrorCode error)
        {
            Condition.IsTrue(
                error == CPRPTErrorCode.None ||
                error == CPRPTErrorCode.NullDestinationObject ||
                error == CPRPTErrorCode.NotSupported ||
                error == CPRPTErrorCode.InvalidParameter);

            if (error == CPRPTErrorCode.None || error == CPRPTErrorCode.NotSupported || error == CPRPTErrorCode.InvalidParameter)
            {
                Condition.IsTrue(isDestinationInRequestExist);
            }

            if (error == CPRPTErrorCode.NullDestinationObject)
            {
                Condition.IsTrue(!isDestinationInRequestExist && !isPropertiesDeleted && !isChangedInDB && !isOverwriteDestination);
            }

            if (error == CPRPTErrorCode.InvalidParameter || error == CPRPTErrorCode.NotSupported)
            {
                Condition.IsTrue(!isPropertiesDeleted && !isChangedInDB && !isOverwriteDestination);
            }

            // Test synchronous and asynchronous situation through "isClientWantAsynchronous", "isReturnedRopProgress" and "isWorkSynchronously"
            if (!isClientWantAsynchronous)
            {
                Condition.IsTrue(!isReturnedRopProgress);
                isWorkSynchronously = true;
                ModelHelper.CaptureRequirement(
                    15204,
                    "[In RopCopyProperties ROP Request Buffer] WantAsynchronous: If this field is set to zero, then the server performs the ROP[RopCopyProperties] synchronously.");

                // To test the CopyFlags
                // Distinguish behavior on folder object, then common behaviors on message and attachment objects
                if (isDestinationInRequestExist)
                {
                    if (clientCopyFlag == CopyFlags.None)
                    {
                        isCopyPropertiesSuccess = true;
                        Condition.IsTrue(error == CPRPTErrorCode.None && isOverwriteDestination && !isPropertiesDeleted);

                        if (globalObj == ServerObjectType.Folder)
                        {
                            Condition.IsTrue(isChangedInDB);

                            ModelHelper.CaptureRequirement(
                                503,
                                @"[In Processing RopCopyProperties] In the case of Folder objects, the changes on the source
                        and destination MUST be immediately persisted.");
                        }
                        else
                        {
                            Condition.IsFalse(isChangedInDB);
                        }
                    }
                    else if (clientCopyFlag == CopyFlags.NoOverWrite)
                    {
                        isCopyPropertiesSuccess = true;
                        Condition.IsTrue(error == CPRPTErrorCode.None && !isOverwriteDestination && !isChangedInDB && !isPropertiesDeleted);

                        ModelHelper.CaptureRequirement(
                            146,
                            @"[In RopCopyProperties ROP] The RopCopyProperties ROP ([MS-OXCROPS] section 2.2.8.11) copies or moves one or more properties from one object to another. ");

                        ModelHelper.CaptureRequirement(
                            264,
                            @"[In RopCopyProperties ROP Request Buffer] CopyFlags: NoOverwrite: If this bit[bit 0x02] is set, properties that already have a value on the destination object will not be overwritten;");

                        ModelHelper.CaptureRequirement(
                            879,
                            @"[In Processing RopCopyProperties] If the NoOverwrite flag is set in the CopyFlags field,
                        the server MUST NOT overwrite any properties that already have a value on the destination object.");

                        ModelHelper.CaptureRequirement(
                                15901,
                                @"[In RopCopyProperties ROP Request Buffer] CopyFlags: otherwise [If this bit is not set to 0x01], properties are copied.");
                    }
                    else if (clientCopyFlag == CopyFlags.MoveAndNoOverWrite)
                    {
                        if (requirementContainer[86701])
                        {
                            if (globalObj == ServerObjectType.Folder)
                            {
                                Condition.IsTrue(error == CPRPTErrorCode.NotSupported);
                            }
                            else
                            {
                                isCopyPropertiesSuccess = true;
                                Condition.IsTrue(!isPropertiesDeleted && !isOverwriteDestination && error == CPRPTErrorCode.None && !isChangedInDB);
                                ModelHelper.CaptureRequirement(
                                    86701,
                                    @"Implementation does support combination of the Move bit and the NoOverwrite bit. <2> Section 2.2.10.1: Exchange 2003 and Exchange 2007 support the combination of the Move bit and the NoOverwrite bit in the CopyFlags field.");
                            }
                        }

                        if (requirementContainer[86502])
                        {
                            Condition.IsTrue(error == CPRPTErrorCode.InvalidParameter);
                            ModelHelper.CaptureRequirement(
                                86502,
                                @"[In RopCopyProperties ROP Request Buffer] CopyFlags: Implementation does not support the combination of these bit (bit 0x01 and bit 0x02) in CopyFlags.(Microsoft Exchange Server 2010 and above follow this behavior)");
                        }
                    }
                    else if (clientCopyFlag == CopyFlags.Move)
                    {
                        if (globalObj != ServerObjectType.Folder)
                        {
                            Condition.IsTrue(error == CPRPTErrorCode.None);
                            Condition.IsTrue(isOverwriteDestination);
                            ModelHelper.CaptureRequirement(
                                265,
                                @"[In RopCopyProperties ROP Request Buffer] CopyFlags: NoOverwrite:  otherwise(If this bit is not set to 0x02), they [properties that already have a value on the destination object] are overwritten.");

                            if (requirementContainer[86704])
                            {
                                Condition.IsTrue(isPropertiesDeleted);
                                ModelHelper.CaptureRequirement(
                                    86704,
                                    @"Implementation does remove the properties from the source object, [if the Move flag is set in the CopyFlags field of the ROP request buffer.](<6> Section 3.2.5.7: Exchange 2003 and Exchange 2007 remove the properties from the source object.)");

                                ModelHelper.CaptureRequirement(
                                    159,
                                    @"[In RopCopyProperties ROP Request Buffer] CopyFlags: If this bit[bit 0x01] is set, properties are moved");
                            }

                            if (requirementContainer[50101])
                            {
                                Condition.IsTrue(!isPropertiesDeleted);
                                ModelHelper.CaptureRequirement(
                                    50101,
                                    @"[In Processing RopCopyProperties] Implementation doesn't delete the copied properties from the source object, if the move flag is set in the CopyFlags field of the ROP request buffer.(Microsoft Exchange Server 2010 and above follow this behavior.)");
                            }
                        }
                    }
                    else if (clientCopyFlag == CopyFlags.Other)
                    {
                        if (requirementContainer[86705])
                        {
                            if (globalObj != ServerObjectType.Folder)
                            {
                                Condition.IsTrue(error == CPRPTErrorCode.None);

                                ModelHelper.CaptureRequirement(
                                    86705,
                                    @"Implementation does ignore invalid bits and doesn't return the InvalidParameter error code. <7> Section 3.2.5.7: Exchange 2003 and Exchange 2007 ignore invalid bits and do not return the InvalidParameter error code (0x80070057).");
                            }
                            else
                            {
                                Condition.IsTrue(error == CPRPTErrorCode.NotSupported);
                            }
                        }

                        if (requirementContainer[88001])
                        {
                            Condition.IsTrue(error == CPRPTErrorCode.InvalidParameter);
                            ModelHelper.CaptureRequirement(
                                88001,
                                @"[In Processing RopCopyProperties] Implementation does return an InvalidParameter error (0x80070057) ([MS-OXCDATA] section 2.4), if any other bits are set in the CopyFlags field.(Microsoft Exchange Server 2010 and above follow this behavior)");
                        }
                    }
                }
            }
            else
            {
                if (!isReturnedRopProgress)
                {
                    isWorkSynchronously = true;
                    ModelHelper.CaptureRequirement(
                        153,
                        @"[In RopCopyProperties ROP Request Buffer] WantAsynchronous: If this field is set to nonzero, the ROP is processed either synchronously or asynchronously.");

                    ModelHelper.CaptureRequirement(
                        504,
                        @"[In Processing RopCopyProperties] If the client requests asynchronous execution, then the server can execute this ROP asynchronously.");

                    ModelHelper.CaptureRequirement(
                        50402,
                        @"[In Processing RopCopyProperties] During asynchronous processing, the server can indicate that the operation is still being processed by returning a RopProgress ROP response ([MS-OXCROPS] section 2.2.8.13), or it can indicate that the operation has already completed by returning a RopCopyProperties ROP response.");
                }
            }
        }
예제 #14
0
        public static void RopWriteAndCommitStreamMethod(out CPRPTErrorCode error)
        {
            // Exchange 2010 does not implement this ROP.
            Condition.IsTrue(requirementContainer[752]);
            isStreamWriteSuccess = true;

            error = CPRPTErrorCode.None;
        }
        /// <summary>
        /// This method is used to write the stream of bytes into a Stream object. 
        /// </summary>
        /// <param name="openFlag">Specifies the OpenModeFlags of the stream.</param>
        /// <param name="isExceedMax">Indicates whether the write will exceed the maximum stream size.</param>
        /// <param name="error"> Specifies the ErrorCode when WriteStream failed:STG_E_ACCESSDENIED
        /// 0x80030005 Write access is denied.When stream is opened with ReadOnly flag.</param>
        public void RopWriteStreamMethod(OpenModeFlags openFlag, bool isExceedMax, out CPRPTErrorCode error)
        {
            TaggedPropertyValue[] tagPtyValues = new TaggedPropertyValue[1];
            if (this.cprptCurrentType == ServerObjectType.Folder)
            {
                tagPtyValues[0] = this.GetTaggedPropertyTag(ObjectToOperate.ThirdObject);
            }
            else
            {
                tagPtyValues[0] = this.GetTaggedPropertyTag(this.cprptCurrentObj);
            }

            PropertyTag[] ptyTags;
            ptyTags = new PropertyTag[1];
            ptyTags[0] = tagPtyValues[0].PropertyTag;

            uint objHandle = 0;
            switch (this.cprptCurrentObj)
            {
                case ObjectToOperate.FirstObject:
                    objHandle = this.cprptFirstObjectHandle;
                    break;
                case ObjectToOperate.SecondObject:
                    objHandle = this.cprptSecondObjectHandle;
                    break;
                default:
                    break;
            }

            RopGetPropertiesSpecificResponse getPropertiesSpecificResponse = this.RopGetPropertiesSpecific(objHandle, 0, 0, ptyTags);
            bool canBeRetrieval = false;
            bool isChangInDB = true;
            bool forErrorCode = false;
            if (isExceedMax)
            {
                this.RopSeekStream(this.cprptCurrentHandle, (byte)Origin.Beginning, int.MaxValue, true);
            }

            RopSeekStreamResponse seekStreamResponse1 = this.RopSeekStream(this.cprptCurrentHandle, (byte)Origin.Current, 0, true);
            RopWriteStreamResponse writeStreamResponse = this.RopWriteStream(this.cprptCurrentHandle, WriteData, false);
            RopSeekStreamResponse seekStreamResponse2 = this.RopSeekStream(this.cprptCurrentHandle, (byte)Origin.Current, 0, true);
            bool isWriteSizeElemetRight = false;
            if (seekStreamResponse2.NewPosition - seekStreamResponse1.NewPosition == writeStreamResponse.WrittenSize)
            {
                isWriteSizeElemetRight = true;
            }

            if (writeStreamResponse.ReturnValue.Equals((uint)CPRPTErrorCode.None))
            {
                this.RopSeekStream(this.cprptCurrentHandle, (byte)Origin.Current, (long)(0 - WriteData.Length), true);
                RopReadStreamResponse readStreamResponse = this.RopReadStream(this.cprptCurrentHandle, (ushort)WriteData.Length, 0x70000000, false);
                if (WriteData == Encoding.ASCII.GetString(readStreamResponse.Data))
                {
                    canBeRetrieval = true;
                }

                RopGetPropertiesSpecificResponse getPropertiesSpecificResponse1 = this.RopGetPropertiesSpecific(objHandle, 0, 0, ptyTags);
                if (Common.CompareByteArray(getPropertiesSpecificResponse.RowData.PropertyValues[0].Value, getPropertiesSpecificResponse1.RowData.PropertyValues[0].Value))
                {
                    isChangInDB = false;
                }
            }
            else
            {
                forErrorCode = true;
            }

            this.VerifyRopWriteStream(writeStreamResponse, openFlag, WriteData, canBeRetrieval, isChangInDB, forErrorCode, isWriteSizeElemetRight);

            error = (CPRPTErrorCode)writeStreamResponse.ReturnValue;
        }
예제 #16
0
        public static void RopSeekStreamMethod(SeekStreamCondition condition, out bool isStreamExtended, out CPRPTErrorCode error)
        {
            Condition.IsTrue(isInitialized && isStreamOpenedSuccess);

            if (condition == SeekStreamCondition.MovedBeyondMaxStreamSize)
            {
                error = CPRPTErrorCode.StreamSeekError;
                isStreamExtended = false;

                ModelHelper.CaptureRequirement(
                    582,
                    "[In Processing RopSeekStream] If the client requests the seek pointer be moved beyond 2^31 bytes, the server MUST return the StreamSeekError error code in the ReturnValue field of the ROP response buffer.");
            }
            else if (condition == SeekStreamCondition.MovedBeyondEndOfStream)
            {
                error = CPRPTErrorCode.None;
                isStreamExtended = true;
                ModelHelper.CaptureRequirement(
                    583,
                    @"[In Processing RopSeekStream] If the client requests the seek pointer be moved beyond the end of the stream, the stream is extended, and zeros filled to the new seek location.");
            }
            else if (condition == SeekStreamCondition.OriginInvalid)
            {
                error = CPRPTErrorCode.StreamInvalidParam;
                isStreamExtended = false;
            }
            else
            {
                error = CPRPTErrorCode.None;
                isStreamExtended = false;
            }
        }
        /// <summary>
        /// This method is used to copy a specified number of bytes from the current seek pointer in the source stream to the current seek pointer in the destination stream. 
        /// </summary>
        /// <param name="isDestinationExist">Specified the whether the destination existed.</param>
        /// <param name="isReadWriteSuccess">When call success:The server MUST read the number of BYTES
        /// requested from the source Stream object, and write those bytes into the destination Stream object .</param>
        /// <param name="error">If Destination object does not exist .Expect DestinationNullObject error.</param>
        public void RopCopyToStreamMethod(bool isDestinationExist, out bool isReadWriteSuccess, out CPRPTErrorCode error)
        {
            isReadWriteSuccess = false;
            error = CPRPTErrorCode.None;

            // The source handle.
            uint firstHandle = this.cprptFirstHandle;

            // The destination handle.
            uint secondHandle = InvalidHandle;
            if (isDestinationExist)
            {
                secondHandle = this.cprptSecondHandle;
            }

            RopGetStreamSizeResponse getStreamSizeRes = this.RopGetStreamSize(firstHandle, true);
            ulong byteCount = getStreamSizeRes.StreamSize;

            // Set position of the source handle to the beginning of stream.
            this.RopSeekStream(firstHandle, (byte)Origin.Beginning, ConstValues.RopSeekStreamOffsetZero, true);
            if (isDestinationExist)
            {
                // Set position of the destination handle to the beginning of stream.
                this.RopSeekStream(secondHandle, (byte)Origin.Beginning, ConstValues.RopSeekStreamOffsetZero, true);
            }

            RopCopyToStreamResponse copyToStreamResponse = this.RopCopyToStream(firstHandle, secondHandle, (byte)HandleIndex.FirstIndex, (byte)HandleIndex.SecondIndex, byteCount);
            bool isCopyRightDataCount = false;
            if (isDestinationExist)
            {
                isCopyRightDataCount = byteCount == copyToStreamResponse.WrittenByteCount;
            }

            bool destHandleIsRight = false;
            if (copyToStreamResponse.ReturnValue.Equals((uint)CPRPTErrorCode.NullDestinationObject))
            {
                destHandleIsRight = copyToStreamResponse.DestHandleIndex == (uint)HandleIndex.SecondIndex;
            }

            this.VerifyRopCopyToStream(copyToStreamResponse, isDestinationExist, isCopyRightDataCount, destHandleIsRight);

            if (copyToStreamResponse.ReturnValue == (uint)CPRPTErrorCode.None)
            {
                isReadWriteSuccess = true;
            }

            if (copyToStreamResponse.ReturnValue == (uint)CPRPTErrorCode.NullDestinationObject)
            {
                isReadWriteSuccess = false;
                error = CPRPTErrorCode.NullDestinationObject;
            }
        }
예제 #18
0
        public static void RopLockRegionStreamMethod(PreStateBeforeLock preState, out CPRPTErrorCode error)
        {
            Condition.IsTrue(isInitialized && isStreamOpenedSuccess);

            // RopUnlockRegionStream is only implemented on Exchange server 2007.
            Condition.IsTrue(requirementContainer[750]);
            error = CPRPTErrorCode.None;
            if (preState == PreStateBeforeLock.WithExpiredLock || preState == PreStateBeforeLock.Normal)
            {
                error = CPRPTErrorCode.None;
                ModelHelper.CaptureRequirement(
                     610,
                     "[In Processing RopLockRegionStream] If the server implements this ROP, if all previous locks are expired, or if there are no previous locks, the server MUST grant the requesting client a new lock.");
            }

            isStreamLocked = true;
        }
        /// <summary>
        /// This method is used to copy or move one or more properties from one object to another. 
        /// </summary>
        /// <param name="copyFlag">Specifies the CopyFlags in the call request.</param>
        /// <param name="isWantAsynchronousZero">Indicates whether WantAsynchronous parameter in call request is zero.</param>
        /// <param name="isDestinationExist">Indicates whether destination object is exist for [RopCopyProperties]</param>
        /// <param name="isPropertiesDeleted">If CopyFlags is set to Move,Source object will be deleted after copy to.</param>
        /// <param name="isChangedInDB">Indicates whether the change is submit to DB.</param>
        /// <param name="isOverwriteDestination">If CopyFlags is set to NoOverWrite,Destination should not be overwritten.</param>
        /// <param name="isReturnedRopProgress">If this ROP is performed Asynchronously,RopProgress response returned 
        /// instead of RopCopyProperties response.</param>
        /// <param name="error">If destination object is not exist,NullDestinationObject error will be returned.</param>
        public void RopCopyPropertiesMethod(
            CopyFlags copyFlag,
            bool isWantAsynchronousZero,
            bool isDestinationExist,
            out bool isPropertiesDeleted,
            out bool isChangedInDB,
            out bool isOverwriteDestination,
            out bool isReturnedRopProgress,
            out CPRPTErrorCode error)
        {
            // Check if there are conflict SHOULD/MAY settings 
            this.CheckRequirementConflict(86701, 86502);
            this.CheckRequirementConflict(86704, 50101);
            this.CheckRequirementConflict(86705, 88001);

            #region Set parameter
            isPropertiesDeleted = false;
            isChangedInDB = false;
            isOverwriteDestination = false;
            isReturnedRopProgress = false;
            error = CPRPTErrorCode.None;

            byte copyFlags = (byte)RopCopyPropertiesCopyFlags.None;
            switch (copyFlag)
            {
                case CopyFlags.None:
                    copyFlags = (byte)RopCopyPropertiesCopyFlags.None;
                    break;
                case CopyFlags.Move:
                    copyFlags = (byte)RopCopyPropertiesCopyFlags.Move;
                    break;
                case CopyFlags.NoOverWriteAndDestPropNull:
                    copyFlags = (byte)RopCopyPropertiesCopyFlags.NoOverwrite;
                    break;
                case CopyFlags.NoOverWrite:
                    copyFlags = (byte)RopCopyPropertiesCopyFlags.NoOverwrite;
                    break;
                case CopyFlags.MoveAndNoOverWrite:
                    copyFlags = (byte)RopCopyPropertiesCopyFlags.MoveAndOverwrite;
                    break;
                case CopyFlags.Other:
                    copyFlags = (byte)4;
                    break;
                default:
                    this.Site.Assert.Fail("Invalid RopCopyPropertiesCopyFlags enum vaule {0}", copyFlag);
                    break;
            }

            byte wantAsynchronous = 0;
            if (!isWantAsynchronousZero)
            {
                wantAsynchronous = 1;
            }

            uint sourceHandle = this.cprptSecondHandle;
            uint destHandle = InvalidHandle;
            #endregion

            #region Set source and destination handle property
            TaggedPropertyValue[] sourceTag = new TaggedPropertyValue[1];
            sourceTag[0] = this.GetTaggedPropertyTag(ObjectToOperate.FirstObject);
            sourceTag[0].Value = Common.AddInt16LengthBeforeBinaryArray(sourceTag[0].Value);

            TaggedPropertyValue[] destTag = new TaggedPropertyValue[1];
            destTag[0] = this.GetTaggedPropertyTag(ObjectToOperate.FirstObject);
            destTag[0].Value = Common.AddInt16LengthBeforeBinaryArray(destTag[0].Value);
            destTag[0].Value[2]++;

            if (isDestinationExist)
            {
                destHandle = this.cprptFirstHandle;
                if (this.cprptCurrentType == ServerObjectType.Folder)
                {
                    RopCreateFolderResponse createFolderResponse;
                    string displayName = SubFolder;
                    sourceHandle = this.RopCreateFolder(sourceHandle, out createFolderResponse, displayName, "Comment: " + displayName, true);
                }

                this.RopSetProperties(destHandle, destTag, true);
                if (this.cprptCurrentType == ServerObjectType.Message)
                {
                    this.RopSaveChangesMessage(destHandle, true);
                }
                else if (this.cprptCurrentType == ServerObjectType.Attachment)
                {
                    this.RopSaveChangesAttachment(destHandle, true);
                    this.RopSaveChangesMessage(cprptMessageHandle[0], true);
                }

                #region Store destHandle property
                // Search property value for the first object
                TaggedPropertyValue tag = new TaggedPropertyValue
                {
                    PropertyTag = destTag[0].PropertyTag
                };
                RopGetPropertiesSpecificResponse destTagValue = this.RopGetPropertiesSpecific(destHandle, ConstValues.PropertySizeLimitNone, ConstValues.WantUnicodeNo, new PropertyTag[] { tag.PropertyTag });
                tag.Value = destTagValue.RowData.PropertyValues[0].Value;

                // Store the TaggedPropertyValue for further verification
                this.tagPropertyValuesToVerification.Clear();
                switch (this.cprptCurrentType)
                {
                    case ServerObjectType.Folder:
                        this.tagPropertyValuesToVerification.Add(ConstValues.ServerObjectTypeFolderKey, tag);
                        break;
                    case ServerObjectType.Message:
                        this.tagPropertyValuesToVerification.Add(ConstValues.ServerObjectTypeMessageKey, tag);
                        break;
                    case ServerObjectType.Attachment:
                        this.tagPropertyValuesToVerification.Add(ConstValues.ServerObjectTypeAttachmentKey, tag);
                        break;
                    default:
                        break;
                }
                #endregion
            }

            this.RopSetProperties(sourceHandle, sourceTag, true);
            if (this.cprptCurrentType == ServerObjectType.Message)
            {
                this.RopSaveChangesMessage(sourceHandle, true);
            }
            else if (this.cprptCurrentType == ServerObjectType.Attachment)
            {
                this.RopSaveChangesAttachment(sourceHandle, true);
                this.RopSaveChangesMessage(cprptMessageHandle[0], true);
            }
            #endregion

            // Add sourceTags[1] to verify PropertyProblems structure
            PropertyTag[] sourceTags = new PropertyTag[2];
            sourceTags[0] = sourceTag[0].PropertyTag;
            sourceTags[1] = sourceTag[0].PropertyTag;
            sourceTags[1].PropertyId--;

            object responseObj = this.RopCopyProperties(sourceHandle, destHandle, (byte)HandleIndex.FirstIndex, (byte)HandleIndex.SecondIndex, wantAsynchronous, copyFlags, sourceTags);

            if (responseObj is RopProgressResponse)
            {
                isReturnedRopProgress = true;
            }
            else
            {
                RopCopyPropertiesResponse copyPropertiesResponse = (RopCopyPropertiesResponse)responseObj;

                if (copyPropertiesResponse.ReturnValue != (uint)CPRPTErrorCode.None)
                {
                    #region Return error
                    switch ((CPRPTErrorCode)copyPropertiesResponse.ReturnValue)
                    {
                        case CPRPTErrorCode.NullDestinationObject:
                            error = CPRPTErrorCode.NullDestinationObject;
                            break;
                        case CPRPTErrorCode.NotSupported:
                            error = CPRPTErrorCode.NotSupported;
                            break;
                        case CPRPTErrorCode.InvalidParameter:
                            error = CPRPTErrorCode.InvalidParameter;
                            break;
                        default:
                            error = CPRPTErrorCode.Other;
                            break;
                    }
                    #endregion

                    this.VerifyRopCopyProperties(copyPropertiesResponse, this.cprptCurrentType, copyFlag, false);
                }
                else
                {
                    #region Check if the property is changed in DB
                    string objKey;
                    switch (this.cprptCurrentType)
                    {
                        case ServerObjectType.Folder:
                            objKey = ConstValues.ServerObjectTypeFolderKey;
                            break;
                        case ServerObjectType.Message:
                            objKey = ConstValues.ServerObjectTypeMessageKey;
                            break;
                        case ServerObjectType.Attachment:
                            objKey = ConstValues.ServerObjectTypeAttachmentKey;
                            break;
                        default:
                            objKey = string.Empty;
                            break;
                    }

                    bool isPropertyFound;
                    byte[] propertyValueBeforeSave = this.Session2GetPropertyData(objKey, destTag[0].PropertyTag, out isPropertyFound);

                    isChangedInDB = !Common.CompareByteArray(propertyValueBeforeSave, this.tagPropertyValuesToVerification[objKey].Value);
                    #endregion

                    this.VerifyRopCopyProperties(copyPropertiesResponse, this.cprptCurrentType, copyFlag, isPropertyFound);

                    #region Check if property is overwritten
                    if (isDestinationExist)
                    {
                        RopGetPropertiesSpecificResponse overWriteRes = this.RopGetPropertiesSpecific(destHandle, ConstValues.PropertySizeLimitNone, ConstValues.WantUnicodeNo, new PropertyTag[] { destTag[0].PropertyTag });
                        isOverwriteDestination = Common.CompareByteArray(overWriteRes.RowData.PropertyValues[0].Value, sourceTag[0].Value);
                    }
                    #endregion

                    #region Check if property is deleted
                    // The message and attachment objects must apply the changes to database
                    if (this.cprptCurrentType == ServerObjectType.Message)
                    {
                        this.RopSaveChangesMessage(sourceHandle, true);
                    }
                    else if (this.cprptCurrentType == ServerObjectType.Attachment)
                    {
                        this.RopSaveChangesAttachment(sourceHandle, true);
                        this.RopSaveChangesMessage(cprptMessageHandle[1], true);
                    }

                    switch (this.cprptCurrentType)
                    {
                        case ServerObjectType.Folder:
                            objKey = "Folder2";
                            break;
                        case ServerObjectType.Message:
                            objKey = "Message2";
                            break;
                        case ServerObjectType.Attachment:
                            objKey = "Attachment2";
                            break;
                        default:
                            objKey = string.Empty;
                            break;
                    }

                    if (this.cprptCurrentType == ServerObjectType.Folder)
                    {
                        RopGetPropertiesSpecificResponse tagValueRes = this.RopGetPropertiesSpecific(sourceHandle, ConstValues.PropertySizeLimitNone, ConstValues.WantUnicodeNo, new PropertyTag[] { sourceTag[0].PropertyTag });
                        if (tagValueRes.RowData.PropertyValues[0].Value == null)
                        {
                            isPropertiesDeleted = true;
                        }
                        else
                        {
                            byte[] expectedNotFoundError = new byte[] { 0x0f, 0x01, 0x04, 0x80 };
                            isPropertiesDeleted = Common.CompareByteArray(expectedNotFoundError, tagValueRes.RowData.PropertyValues[0].Value);
                        }
                    }
                    else
                    {
                        if (this.cprptCurrentType == ServerObjectType.Attachment && copyFlag == CopyFlags.Move && Common.IsRequirementEnabled(86704, this.Site))
                        {
                            isPropertiesDeleted = true;
                        }
                        else
                        {
                            byte[] propertyValueNow = this.Session2GetPropertyData(objKey, sourceTag[0].PropertyTag, out isPropertyFound);
                            if (!isPropertyFound)
                            {
                                isPropertiesDeleted = true;
                            }
                            else
                            {
                                byte[] expectedNotFoundError = new byte[] { 0x0f, 0x01, 0x04, 0x80 };
                                isPropertiesDeleted = Common.CompareByteArray(expectedNotFoundError, propertyValueNow);
                            }
                        }
                    }
                    #endregion
                }
            }
        }
        /// <summary>
        /// This method is used to map abstract, client-defined named properties to concrete 16-bit property IDs. 
        /// </summary>
        /// <param name="isTestOrder">Indicates whether to test returned PropertyNames order.</param>
        /// <param name="isCreateFlagSet">Indicates whether the "Create" Flags in request parameter is set.</param>
        /// <param name="isPropertyNameExisting">Indicates whether PropertyName is existing in object mapping.</param>
        /// <param name="specialPropertyName">Specifies PropertyName of request parameter</param>
        /// <param name="isCreatedEntryReturned">If Create Flags is set: If set, indicates that the server MUST create new
        /// entries for any name parameters that are not found in the existing mapping set, and return existing entries for any
        /// name parameters that are found in the existing mapping set.</param>
        /// <param name="error">Specifies the ErrorCode when server reached limit.</param>
        public void RopGetPropertyIdsFromNamesMethod(
            bool isTestOrder,
            bool isCreateFlagSet,
            bool isPropertyNameExisting,
            SpecificPropertyName specialPropertyName,
            out bool isCreatedEntryReturned,
            out CPRPTErrorCode error)
        {
            #region Initialize parameters
            // Specify whether the order in response is the same as that in request.
            bool isOrder = true;

            // Specify whether the property names and ids are mapped.
            bool isNamesAndIdsMapping = false;

            // Set default value for the out parameter.
            isCreatedEntryReturned = false;
            error = CPRPTErrorCode.None;

            // Set value for flags in RopGetPropertyIdsFromNames.
            byte flags = (byte)GetPropertyIdsFromNamesFlags.None;
            if (isCreateFlagSet)
            {
                flags = (byte)GetPropertyIdsFromNamesFlags.Create;
            }

            PropertyName[] propertyNames = null;

            if (isTestOrder)
            {
                propertyNames = new PropertyName[ConstValues.TestPropertyCount];
            }
            else
            {
                propertyNames = new PropertyName[1];
            }

            switch (specialPropertyName)
            {
                case SpecificPropertyName.Kind0x01:
                case SpecificPropertyName.NoConstraint:
                    propertyNames[0] = this.GetPropertyName((byte)Kind.NameField);
                    break;
                case SpecificPropertyName.PS_MAPIAndKind0x01:
                    propertyNames[0] = this.GetPropertyName((byte)Kind.NameField);
                    propertyNames[0].Guid = (new Guid(PSMAPI)).ToByteArray();
                    break;
                case SpecificPropertyName.PS_MAPIAndKind0x00:
                    propertyNames[0] = this.GetPropertyName((byte)Kind.LidField);
                    propertyNames[0].Guid = (new Guid(PSMAPI)).ToByteArray();
                    break;
                default:
                    Site.Assert.Fail("Invalid SpecificPropertyName enum value {0}.", specialPropertyName);
                    break;
            }

            if (!isPropertyNameExisting && !isCreateFlagSet)
            {
                propertyNames[0].Kind = (byte)Kind.NameField;
                propertyNames[0].Name = Encoding.Unicode.GetBytes(PropertyNameNotMapped + "\0");
                propertyNames[0].NameSize = (byte)propertyNames[0].Name.Length;
                propertyNames[0].Guid = (new Guid(PropertyNameNotMappedGuid)).ToByteArray();
            }

            // The existing property ID.
            ushort existId = 0;

            // If the property exists, create it.
            if (isPropertyNameExisting)
            {
                PropertyName[] propertyNameTmp = new PropertyName[1];
                propertyNameTmp[0] = propertyNames[0];
                RopGetPropertyIdsFromNamesResponse ptyNameExistingRes = this.RopGetPropertyIdsFromNames(this.cprptCurrentHandle, (byte)GetPropertyIdsFromNamesFlags.Create, propertyNameTmp, true);
                existId = ptyNameExistingRes.PropertyIds[0].ID;
            }

            // The second property ID.
            ushort secondId = 0;

            // The third property ID.
            ushort thirdId = 0;

            // If the PropertyNames order need to verify, create the second and the third properties.
            if (isTestOrder)
            {
                // Add second property.
                PropertyName[] propertyNameTmp = new PropertyName[1];
                propertyNameTmp[0] = this.GetPropertyName((byte)Kind.NameField);
                propertyNameTmp[0].Name[0]++;
                propertyNameTmp[0].Guid[0]++;
                propertyNames[1] = propertyNameTmp[0];
                RopGetPropertyIdsFromNamesResponse ptyNameExistingRes = this.RopGetPropertyIdsFromNames(this.cprptCurrentHandle, (byte)GetPropertyIdsFromNamesFlags.Create, propertyNameTmp, true);
                secondId = ptyNameExistingRes.PropertyIds[0].ID;

                // Add second property.
                propertyNameTmp[0] = this.GetPropertyName((byte)Kind.NameField);
                propertyNameTmp[0].Name[0]--;
                propertyNameTmp[0].Guid[0]--;
                propertyNames[2] = propertyNameTmp[0];
                ptyNameExistingRes = this.RopGetPropertyIdsFromNames(this.cprptCurrentHandle, (byte)GetPropertyIdsFromNamesFlags.Create, propertyNameTmp, true);
                thirdId = ptyNameExistingRes.PropertyIds[0].ID;
            }
            #endregion

            RopGetPropertyIdsFromNamesResponse getPropertyIdsFromNamesResponse = this.RopGetPropertyIdsFromNames(this.cprptCurrentHandle, flags, propertyNames, false);

            #region When property exists, check if names and ids are mapping
            if (isPropertyNameExisting)
            {
                RopGetNamesFromPropertyIdsResponse getPropertyNamesFromPropertyIdsResponse = this.RopGetNamesFromPropertyIds(this.cprptCurrentHandle, getPropertyIdsFromNamesResponse.PropertyIds);

                // Verify whether property name and id is mapping.
                for (int i = 0; i < getPropertyNamesFromPropertyIdsResponse.PropertyNameCount; i++)
                {
                    if (getPropertyNamesFromPropertyIdsResponse.PropertyNames[i].Kind == (byte)Kind.LidField)
                    {
                        if ((getPropertyNamesFromPropertyIdsResponse.PropertyNames[i].Guid.ToString() == propertyNames[i].Guid.ToString()) &&
                            (getPropertyNamesFromPropertyIdsResponse.PropertyNames[i].Kind == propertyNames[i].Kind) &&
                            (getPropertyNamesFromPropertyIdsResponse.PropertyNames[i].LID == propertyNames[i].LID))
                        {
                            isNamesAndIdsMapping = true;
                        }
                        else
                        {
                            isNamesAndIdsMapping = false;
                            break;
                        }
                    }
                    else if (getPropertyNamesFromPropertyIdsResponse.PropertyNames[i].Kind == (byte)Kind.NameField)
                    {
                        if ((getPropertyNamesFromPropertyIdsResponse.PropertyNames[i].Guid.ToString() == propertyNames[i].Guid.ToString()) &&
                            (getPropertyNamesFromPropertyIdsResponse.PropertyNames[i].Kind == propertyNames[i].Kind) &&
                            (getPropertyNamesFromPropertyIdsResponse.PropertyNames[i].NameSize == propertyNames[i].NameSize) &&
                            (getPropertyNamesFromPropertyIdsResponse.PropertyNames[i].Name.ToString() == propertyNames[i].Name.ToString()))
                        {
                            isNamesAndIdsMapping = true;
                        }
                        else
                        {
                            isNamesAndIdsMapping = false;
                            break;
                        }
                    }
                }
            }
            #endregion

            #region Test order
            if (getPropertyIdsFromNamesResponse.PropertyIds != null && propertyNames.Length == ConstValues.TestPropertyCount && getPropertyIdsFromNamesResponse.PropertyIds.Length == ConstValues.TestPropertyCount)
            {
                if (getPropertyIdsFromNamesResponse.PropertyIds[1].ID != secondId || getPropertyIdsFromNamesResponse.PropertyIds[2].ID != thirdId)
                {
                    isOrder = false;
                }
            }
            #endregion

            this.VerifyRopGetPropertyIdsFromNames((ushort)propertyNames.Length, propertyNames, flags, getPropertyIdsFromNamesResponse, isOrder, this.cprptCurrentType, isPropertyNameExisting, isNamesAndIdsMapping);

            #region Check error and isCreateEnrtyReturned

            switch ((CPRPTErrorCode)getPropertyIdsFromNamesResponse.ReturnValue)
            {
                case CPRPTErrorCode.None:

                    // Verify whether the created entry is returned.
                    if (isCreateFlagSet)
                    {
                        if (isPropertyNameExisting)
                        {
                            isCreatedEntryReturned = false;
                        }
                        else if (getPropertyIdsFromNamesResponse.PropertyIds[0].ID != existId)
                        {
                            isCreatedEntryReturned = true;
                        }
                    }

                    break;
                case CPRPTErrorCode.ecWarnWithErrors:
                    error = CPRPTErrorCode.ecWarnWithErrors;
                    break;
                case CPRPTErrorCode.NotEnoughMemory:
                    error = CPRPTErrorCode.NotEnoughMemory;
                    break;
                default:
                    Site.Assert.Fail("Unexpected RopGetPropertyIdsFromNames error code.Error: 0x{0:X8}", getPropertyIdsFromNamesResponse.ReturnValue);
                    break;
            }

            #endregion
        }
        /// <summary>
        ///  Set common object properties in order to test whether each of them is read-only.
        /// </summary>
        /// <param name="commonProperty">The nine Common Object Properties defined in section 2.2.1</param>
        /// <param name="error">When a property is specified as "read-only for the client", the server MUST
        /// return an error and ignore any request to change the value of that property.</param>
        public void SetCommonObjectProperties(CommonObjectProperty commonProperty, out CPRPTErrorCode error)
        {
            PropertyTag[] proTag = new PropertyTag[1];

            proTag[0] = this.commonProperties[commonProperty];

            this.RopGetPropertiesSpecific(this.cprptCurrentHandle, ConstValues.PropertySizeLimitNone, ConstValues.WantUnicodeNo, proTag);

            error = CPRPTErrorCode.None;
            TaggedPropertyValue[] tags = new TaggedPropertyValue[1];
            tags[0] = new TaggedPropertyValue
            {
                PropertyTag = this.commonProperties[commonProperty]
            };

            switch ((PropertyTypeName)tags[0].PropertyTag.PropertyType)
            {
                case PropertyTypeName.PtypInteger32:
                    tags[0].Value = BitConverter.GetBytes(Convert.ToInt32(CommonValue));
                    break;
                case PropertyTypeName.PtypBinary:
                    tags[0].Value = Common.AddInt16LengthBeforeBinaryArray(Encoding.Unicode.GetBytes(CommonValue));
                    break;
                case PropertyTypeName.PtypTime:
                    tags[0].Value = new byte[ConstValues.PtypTimeSizeInByte];
                    for (int i = 0; i < ConstValues.PtypTimeSizeInByte; i++)
                    {
                        tags[0].Value[i] = (byte)i;
                    }

                    break;
                case PropertyTypeName.PtypString:
                    tags[0].Value = Encoding.Unicode.GetBytes(CommonValue + '\0');
                    break;
                default:
                    break;
            }

            RopSetPropertiesResponse setPtyRes = this.RopSetProperties(this.cprptCurrentHandle, tags, false);
            if (setPtyRes.ReturnValue != (uint)CPRPTErrorCode.None)
            {
                if (setPtyRes.ReturnValue == (uint)CPRPTErrorCode.AccessDenied)
                {
                    error = CPRPTErrorCode.AccessDenied;
                }
                else
                {
                    error = CPRPTErrorCode.Other;
                }
            }
            else
            {
                if (this.cprptCurrentType == ServerObjectType.Message)
                {
                    RopSaveChangesMessageResponse saveChangesMsgRes = this.RopSaveChangesMessage(this.cprptCurrentHandle, false);
                    if (saveChangesMsgRes.ReturnValue == (uint)CPRPTErrorCode.GeneralFailure)
                    {
                        error = CPRPTErrorCode.GeneralFailure;
                    }
                    else
                    {
                        this.RopGetPropertiesSpecific(this.cprptCurrentHandle, ConstValues.PropertySizeLimitNone, ConstValues.WantUnicodeNo, proTag);
                    }
                }
                else if (this.cprptCurrentType == ServerObjectType.Attachment)
                {
                    RopSaveChangesAttachmentResponse saveAttachmentRes = this.RopSaveChangesAttachment(this.cprptCurrentHandle, false);
                    if (saveAttachmentRes.ReturnValue == (uint)CPRPTErrorCode.GeneralFailure)
                    {
                        error = CPRPTErrorCode.GeneralFailure;
                    }
                    else
                    {
                        this.RopGetPropertiesSpecific(this.cprptCurrentHandle, ConstValues.PropertySizeLimitNone, ConstValues.WantUnicodeNo, proTag);
                    }
                }
            }
        }
예제 #22
0
        public static void RopWriteStreamMethod(OpenModeFlags openFlag, bool isExceedMax, out CPRPTErrorCode error)
        {
            Condition.IsTrue(isInitialized && isStreamOpenedSuccess);
            Condition.IsTrue(openFlag == streamOpenFlag);
            Condition.IsTrue(globalObj != ServerObjectType.Logon);
            Condition.IfThen(isExceedMax, openFlag == OpenModeFlags.ReadWrite);

            error = CPRPTErrorCode.None;
            isStreamWriteSuccess = true;
            if (streamOpenFlag == OpenModeFlags.ReadWrite)
            {
                ModelHelper.CaptureRequirement(
                       269,
                       @"[In RopOpenStream ROP Request Buffer] OpenModeFlags: ReadWrite: Open the stream for read/write access.");
            }

            if (streamOpenFlag == OpenModeFlags.ReadOnly)
            {
                error = CPRPTErrorCode.STG_E_ACCESSDENIED;
                isStreamWriteSuccess = false;
                ModelHelper.CaptureRequirement(
                    267,
                    @"[In RopOpenStream ROP Request Buffer] OpenModeFlags: ReadOnly: Open the stream for read-only access.");
            }

            if (isExceedMax)
            {
                // For ExchangeServer 2007, StreamSizeError error code returned.
                if (requirementContainer[86706])
                {
                    error = CPRPTErrorCode.StreamSizeError;
                    ModelHelper.CaptureRequirement(
                        86706,
                        @"[In Appendix A: Product Behavior] Implementation does return the StreamSizeError error code. (<12> Section 3.2.5.13: Exchange 2003 and Exchange 2007 return the StreamSizeError error code if they write less than the amount requested.)");
                }

                // For Exchange 2010, toobig error code returned.
                if (requirementContainer[55707])
                {
                    error = CPRPTErrorCode.ecTooBig;
                    ModelHelper.CaptureRequirement(
                        55707,
                        @"[In Processing RopWriteStream] Implementation does  return the TooBig error code if it writes less than the amount requested.(Microsoft Exchange Server 2010 and above follow this behavior)");
                }

                if (requirementContainer[90102])
                {
                    error = CPRPTErrorCode.ecTooBig;
                    ModelHelper.CaptureRequirement(
                        90102,
                        @"[In Processing RopWriteStream] Implementation does return error code ""0x80040305"" with name ""TooBig"", when the write will exceed the maximum stream size.(Microsoft Exchange Server 2007 and above follow this behavior)");
                }

                isStreamWriteSuccess = false;
            }
        }