
/*
** replsys.sql            1997/02/12 22:03
**
**
** Copyright Microsoft, Inc. 1998, 1999
** All Rights Reserved.
** Use, duplication, or disclosure by the United States Government
** is subject to restrictions as set forth in subdivision (c) (1) (ii)
** of the Rights in Technical Data and Computer Software clause
** at CFR 252.227-7013. Microsoft, Inc. One Microsoft Way, Redmond WA
** 98052.  SQL Server 7.0
*/

dump tran master with no_log
go

exec dbo.sp_configure 'update',1
go
reconfigure with override
go

set ANSI_NULLS off
go

use master
go

exec dbo.sp_MS_upd_sysobj_category 1 --Capture time for use at the end
go

if exists (select * from sysobjects
    where type = 'P '
            and name = 'sp_MSreplcheck_name')
    drop procedure sp_MSreplcheck_name
go

if exists (select * from sysobjects
    where type = 'P '
            and name = 'sp_MSreplcheck_publish')
    drop procedure sp_MSreplcheck_publish
go

if exists (select * from sysobjects
    where type = 'P '
            and name = 'sp_MSsetaccesslist')
    drop procedure sp_MSsetaccesslist
go

if exists (select * from sysobjects
    where type = 'P '
            and name = 'sp_MScheck_subscription')
    drop procedure sp_MScheck_subscription
go

if exists (select * from sysobjects
    where type = 'P '
            and name = 'sp_MSenumcolumns')
    drop procedure sp_MSenumcolumns
go

if exists (select * from sysobjects
    where type = 'P '
            and name = 'sp_MSlocktable')
    drop procedure sp_MSlocktable
go

if exists (select * from sysobjects
    where type = 'P '
            and name = 'sp_MSreplcheck_connection')
    drop procedure sp_MSreplcheck_connection
go

if exists (select * from sysobjects
    where type = 'P '
            and name = 'sp_MSreplcheck_pull')
    drop procedure sp_MSreplcheck_pull
go

if exists (select * from sysobjects
    where type = 'P '
            and name = 'sp_MSreplcheck_qv')
    drop procedure sp_MSreplcheck_qv
go

if exists (select * from sysobjects
	where type = 'P '
			and name = 'sp_MSpublicationcleanup')
	drop procedure sp_MSpublicationcleanup

if exists (select * from sysobjects
	where type = 'P '
			and name = 'sp_MSaddanonymousreplica')
	drop procedure sp_MSaddanonymousreplica
		
if exists (select * from sysobjects
				where type = 'P' and
				name = 'sp_reinitmergepullsubscription')
		drop procedure sp_reinitmergepullsubscription

if exists (select * from sysobjects
	where type = 'P '
			and name = 'sp_expired_subscription_cleanup')
	drop procedure sp_expired_subscription_cleanup
	
	if exists (select * from sysobjects
	where type = 'P '
			and name = 'sp_MSarticlecleanup')
	drop procedure sp_MSarticlecleanup


	if exists (select * from sysobjects
	where type = 'P '
			and name = 'sp_MSdroparticleprocs')
	drop procedure sp_MSdroparticleprocs

	if exists (select * from sysobjects
	where type = 'P '
			and name = 'sp_MSdroparticletriggers')
	drop procedure sp_MSdroparticletriggers

	if exists (select * from sysobjects
	where type = 'P '
			and name = 'sp_MScheckvalidsystables')
	drop procedure sp_MScheckvalidsystables

if exists (select * from sysobjects
    where type = 'P '
            and name = 'sp_MSreplcheck_subscribe')
    drop procedure sp_MSreplcheck_subscribe
go

if exists (select * from sysobjects
    where type = 'P '
            and name = 'sp_replicationoption')
    drop procedure sp_replicationoption
go

if exists (select * from sysobjects
    where type = 'P '
            and name = 'sp_helpreplicationoption')
    drop procedure sp_helpreplicationoption
go

if exists (select * from sysobjects
		where type in ('P ') 
			and name = 'sp_MSmergesubscribedb')
	drop procedure sp_MSmergesubscribedb

if exists (select * from sysobjects
		where type in ('P ') 
			and name = 'sp_MSremovedbreplication')
	drop procedure sp_MSremovedbreplication


if exists (select * from sysobjects
	where type = 'P '
			and name = 'sp_addpullsubscription')
	drop procedure sp_addpullsubscription

if exists (select * from sysobjects
	where type = 'P '
			and name = 'sp_reinitpullsubscription')
	drop procedure sp_reinitpullsubscription
	
if exists (select * from sysobjects
	where type = 'P '
			and name = 'sp_addmergepullsubscription')
	drop procedure sp_addmergepullsubscription

if exists (select * from sysobjects
	where type = 'P '
			and name = 'sp_dropmergepullsubscription')
	drop procedure sp_dropmergepullsubscription

if exists (select * from sysobjects
	where type = 'P '
			and name = 'sp_changemergepullsubscription')
	drop procedure sp_changemergepullsubscription

if exists (select * from sysobjects
	where type = 'P '
			and name = 'sp_helpmergepullsubscription')
	drop procedure sp_helpmergepullsubscription

if exists (select * from sysobjects
	where type = 'P '
			and name = 'sp_MSchange_priority')
	drop procedure sp_MSchange_priority

if exists (select * from sysobjects
		where type = 'P '
				and name = 'sp_MSdrop_mergesystables')
		drop procedure sp_MSdrop_mergesystables

if exists (select * from sysobjects
		where type = 'P '
				and name = 'sp_MScreate_mergesystables')
		drop procedure sp_MScreate_mergesystables
	
if exists (select * from sysobjects
	where type = 'P '
			and name = 'sp_addpullsubscription_agent')
	drop procedure sp_addpullsubscription_agent

if exists (select * from sysobjects
	where type = 'P '
			and name = 'sp_helpsubscription_properties')
	drop procedure sp_helpsubscription_properties

if exists (select * from sysobjects
	where type = 'P '
			and name = 'sp_change_subscription_properties')
	drop procedure sp_change_subscription_properties

if exists (select * from sysobjects
    where type = 'P'
            and name = 'sp_MSget_pullsubsagent_owner')
    drop procedure sp_MSget_pullsubsagent_owner

if exists (select * from sysobjects
    where type = 'P'
            and name = 'sp_MSget_mergepullsubsagent_owner')
    drop procedure sp_MSget_mergepullsubsagent_owner
	
if exists (select * from sysobjects
	where type = 'P '
			and name = 'sp_addmergepullsubscription_agent')
	drop procedure sp_addmergepullsubscription_agent

if exists (select * from sysobjects
	where type = 'P '
			and name = 'sp_droppullsubscription')
	drop procedure sp_droppullsubscription

if exists (select * from sysobjects
	where type = 'P '
			and name = 'sp_vupgrade_publisherdb')
	drop procedure sp_vupgrade_publisherdb

if exists (select * from sysobjects
	where type = 'P '
			and name = 'sp_vupgrade_publisher')
	drop procedure sp_vupgrade_publisher

if exists (select * from sysobjects
	where type = 'P '
			and name = 'sp_helppullsubscription')
	drop procedure sp_helppullsubscription

if exists (select * from sysobjects
	where type = 'P '
			and name = 'sp_MSunmarkreplinfo')
	drop procedure sp_MSunmarkreplinfo

if exists (select * from sysobjects
	where type = 'P '
			and name = 'sp_MSunmarkifneeded')
	drop procedure sp_MSunmarkifneeded

if exists (select * from sysobjects
        where type = 'P '
                and name = 'sp_MStable_has_unique_index')
        drop procedure sp_MStable_has_unique_index

if exists (select * from sysobjects
        where type = 'P '
                and name = 'sp_MSreplraiserror')
        drop procedure sp_MSreplraiserror

if exists (select * from sysobjects
        where type = 'P '
                and name = 'sp_check_sync_trigger')
        drop procedure sp_check_sync_trigger

if exists (select * from sysobjects
        where type = 'P '
                and name = 'sp_MSreplicationcompatlevel')
	drop proc sp_MSreplicationcompatlevel	

if exists (select * from sysobjects
        where type = 'P '
                and name = 'sp_MSgenreplnickname')
	drop proc sp_MSgenreplnickname

if exists (select * from sysobjects
        where type = 'P '
                and name = 'sp_MSenumallpublications')
	drop proc sp_MSenumallpublications

if exists (select * from sysobjects
        where type = 'P '
                and name = 'sp_MSenumtranpublications')
	drop proc sp_MSenumtranpublications

if exists (select * from sysobjects
        where type = 'P '
                and name = 'sp_MSenummergepublications')
	drop proc sp_MSenummergepublications

if exists (select * from sysobjects
        where type = 'P '
                and name = 'sp_MSenum3rdpartypublications')
	drop proc sp_MSenum3rdpartypublications

if exists (select * from sysobjects
				where type = 'P' and
				name = 'sp_MSgetreplicainfo')
		drop procedure sp_MSgetreplicainfo

if exists (select * from sysobjects
    where type = 'P '
           and name = 'sp_subscription_cleanup')
     drop procedure sp_subscription_cleanup  

if exists (select * from sysobjects
    where type = 'P '
           and name = 'sp_mergesubscription_cleanup')
     drop procedure sp_mergesubscription_cleanup  

if exists (select * from sysobjects
	where type = 'P '
			and name = 'sp_MSpad_command')
	drop procedure sp_MSpad_command

if exists (select * from sysobjects
	where type = 'P '
			and name = 'sp_MSflush_command')
	drop procedure sp_MSflush_command

if exists (select * from sysobjects
	where type = 'P '
			and name = 'sp_MSget_colinfo')
	drop procedure sp_MSget_colinfo

if exists (select * from sysobjects
	where type = 'P '
			and name = 'sp_MSget_type')
	drop procedure sp_MSget_type

if exists (select * from sysobjects
	where type = 'P '
			and name = 'sp_MSget_col_position')
	drop procedure sp_MSget_col_position

if exists (select * from sysobjects
	where type = 'P '
			and name = 'sp_MSscript_where_clause')
	drop procedure sp_MSscript_where_clause

if exists (select * from sysobjects
	where type = 'P '
			and name = 'sp_MSscript_params')
	drop procedure sp_MSscript_params

if exists (select * from sysobjects
	where type = 'P '
			and name = 'sp_MSscript_begintrig1')
	drop procedure sp_MSscript_begintrig1

if exists (select * from sysobjects
	where type = 'P '
			and name = 'sp_MSscript_begintrig2')
	drop procedure sp_MSscript_begintrig2

if exists (select * from sysobjects
	where type = 'P '
			and name = 'sp_MSscript_endtrig')
	drop procedure sp_MSscript_endtrig

if exists (select * from sysobjects
	where type = 'P '
			and name = 'sp_MSscript_trigger_variables')
	drop procedure sp_MSscript_trigger_variables

if exists (select * from sysobjects
	where type = 'P '
			and name = 'sp_MSscript_trigger_assignment')
	drop procedure sp_MSscript_trigger_assignment

if exists (select * from sysobjects
	where type = 'P '
			and name = 'sp_MSscript_trigger_fetch_statement')
	drop procedure sp_MSscript_trigger_fetch_statement

if exists (select * from sysobjects
	where type = 'P '
			and name = 'sp_MSscript_trigger_exec_rpc')
	drop procedure sp_MSscript_trigger_exec_rpc

if exists (select * from sysobjects
	where type = 'P '
			and name = 'sp_MSscript_trigger_update_checks')
	drop procedure sp_MSscript_trigger_update_checks

if exists (select * from sysobjects
	where type = 'P '
			and name = 'sp_MSscript_trigger_updates')
	drop procedure sp_MSscript_trigger_updates

if exists (select * from sysobjects
	where type = 'P '
			and name = 'sp_MSscript_singlerow_trigger')
	drop procedure sp_MSscript_singlerow_trigger

if exists (select * from sysobjects
	where type = 'P '
			and name = 'sp_MSscript_multirow_trigger')
	drop procedure sp_MSscript_multirow_trigger

if exists (select * from sysobjects
	where type = 'P '
			and name = 'sp_MSscript_sync_ins_trig')
	drop procedure sp_MSscript_sync_ins_trig

if exists (select * from sysobjects
	where type = 'P '
			and name = 'sp_MSscript_sync_upd_trig')
	drop procedure sp_MSscript_sync_upd_trig

if exists (select * from sysobjects
	where type = 'P '
			and name = 'sp_MSscript_sync_del_trig')
	drop procedure sp_MSscript_sync_del_trig

if exists (select * from sysobjects
	where type = 'P '
			and name = 'sp_MSget_synctran_column')
	drop procedure sp_MSget_synctran_column

if exists (select * from sysobjects
	where type = 'P '
			and name = 'sp_check_for_sync_trigger')
	drop procedure sp_check_for_sync_trigger

if exists (select * from sysobjects
	where type = 'P '
			and name = 'sp_addsynctriggers')
	drop procedure sp_addsynctriggers

if exists (select * from sysobjects
		where type = 'P '
			and name = 'sp_helpreplicationdboption')
	drop procedure sp_helpreplicationdboption

if exists (select * from sysobjects
		where type = 'P' and name = 'sp_MSgetreplnick')
	drop procedure sp_MSgetreplnick
		
if exists (select * from sysobjects
		where type = 'P' and name = 'sp_MStestbit')		
	drop procedure sp_MStestbit
		
if exists (select * from sysobjects
		where type = 'P' and name = 'sp_MSsetbit')
	drop procedure sp_MSsetbit
		
		
if exists (select * from sysobjects
		where type = 'P' and name = 'sp_MSinsertcontents')
	drop procedure sp_MSinsertcontents
		
if exists (select * from sysobjects
		where type = 'P' and name = 'sp_MSupdatecontents')
	drop procedure sp_MSupdatecontents
			
if exists (select * from sysobjects
		where type = 'P' and name = 'sp_MSdeletecontents')
	drop procedure sp_MSdeletecontents

if exists (select * from sysobjects
		where type = 'P '
			and name = 'sp_MSadd_repl_job')
	drop procedure sp_MSadd_repl_job

IF EXISTS (select * from sysobjects where
   name = 'sp_MScheck_agent_instance' and type = 'P')
      DROP PROCEDURE sp_MScheck_agent_instance

if exists (select * from sysobjects
		where name = 'xp_mergexpusage')
	execute dbo.sp_dropextendedproc 'xp_mergexpusage'

if exists (select * from sysobjects 
		where name = 'sp_get_distributor' 
				and type = 'P')
	  drop procedure sp_get_distributor

if exists (select * from sysobjects 
		where name = 'sp_MSrepl_addrolemember' 
				and type = 'P')
	  drop procedure sp_MSrepl_addrolemember

if exists (select * from sysobjects 
		where name = 'sp_MSrepl_droprolemember' 
				and type = 'P')
	  drop procedure sp_MSrepl_droprolemember

if exists (select * from sysobjects 
		where name = 'sp_table_validation' 
				and type = 'P')
	  drop procedure sp_table_validation

if exists (select * from sysobjects 
		where name = 'sp_MScreate_sub_tables' 
				and type = 'P')
	  drop procedure sp_MScreate_sub_tables

go
if exists (select * from sysobjects 
		where name = 'sp_removedbreplication' 
				and type = 'P')
	  drop procedure sp_removedbreplication

if exists (select * from sysobjects 
		where name = 'sp_removesrvreplication' 
				and type = 'P')
	  drop procedure sp_removesrvreplication

if exists (select * from sysobjects 
		where name = 'sp_vupgrade_subscription_databases' 
				and type = 'P')
	  drop procedure sp_vupgrade_subscription_databases

if exists (select * from sysobjects 
		where name = 'sp_vupgrade_MSsubscription_properties' 
				and type = 'P')
	  drop procedure sp_vupgrade_MSsubscription_properties

if exists (select * from sysobjects 
		where name = 'sp_vupgrade_mergetables' 
				and type = 'P')
	  drop procedure sp_vupgrade_mergetables

if exists (select * from sysobjects 
		where name = 'sp_vupgrade_replication' 
				and type = 'P')
	  drop procedure sp_vupgrade_replication

if exists (select * from sysobjects 
		where name = 'sp_vupgrade_replmsdb' 
				and type = 'P')
	  drop procedure sp_vupgrade_replmsdb

if exists (select * from sysobjects 
		where name = 'sp_restoredbreplication' 
				and type = 'P')
	  drop procedure sp_restoredbreplication

if exists (select * from sysobjects 
		where name = 'sp_MSget_publisher_rpc' 
				and type = 'P')
	  drop procedure sp_MSget_publisher_rpc

if exists (select * from sysobjects 
		where name = 'sp_link_publication' 
				and type = 'P')
	  drop procedure sp_link_publication

if exists (select * from sysobjects 
		where name = 'sp_MS_replication_installed' 
				and type = 'P')
	  drop procedure sp_MS_replication_installed

if exists (select * from sysobjects 
		where name = 'sp_MSunc_to_drive' 
				and type = 'P')
	  drop procedure sp_MSunc_to_drive

if exists (select * from sysobjects 
		where name = 'sp_MSdrop_object' 
				and type = 'P')
	  drop procedure sp_MSdrop_object

if exists (select * from sysobjects 
		where name = 'sp_MSregistersubscription' 
				and type = 'P')
	  drop procedure sp_MSregistersubscription

if exists (select * from sysobjects 
		where name = 'sp_MSunregistersubscription' 
				and type = 'P')
	  drop procedure sp_MSunregistersubscription

if exists (select * from sysobjects 
		where name = 'sp_MSrepl_linkedservers_rowset' 
				and type = 'P')
	  drop procedure sp_MSrepl_linkedservers_rowset

if exists (select * from sysobjects 
		where name = 'sp_MSrepl_isdbowner' 
				and type = 'P')
	  drop procedure sp_MSrepl_isdbowner

if exists (select * from sysobjects 
		where name = 'sp_MSget_qualified_name' 
				and type = 'P')
	  drop procedure sp_MSget_qualified_name

if exists (select * from sysobjects 
		where name = 'sp_MSscript_pkvar_assignment' 
				and type = 'P')
	  drop procedure sp_MSscript_pkvar_assignment
go

if exists (select * from sysobjects 
		where name = 'sp_MSget_jobstate' 
				and type = 'P')
	  drop procedure sp_MSget_jobstate

go

if exists (select * from sysobjects
    where type = 'P '
            and name = 'sp_MSget_publication_from_taskname')
    drop procedure sp_MSget_publication_from_taskname
go

if exists (select * from sysobjects
    where type = 'P '
            and name = 'sp_MSrepl_check_server')
    drop procedure sp_MSrepl_check_server
go

if exists (select * from sysobjects
    where type = 'P '
            and name = 'sp_MSreset_synctran_bit')
    drop procedure sp_MSreset_synctran_bit
go

sp_addextendedproc 'xp_mergexpusage', 'xprepl.dll'
go

grant exec on xp_mergexpusage to public
go

if exists (select * from sysobjects
		where name = 'xp_showlineage')
	execute dbo.sp_dropextendedproc 'xp_showlineage'
go

sp_addextendedproc 'xp_showlineage', 'xprepl.dll'
go

grant exec on xp_showlineage to public
go

if exists (select * from sysobjects
		where name = 'xp_updatelineage')
	execute dbo.sp_dropextendedproc 'xp_updatelineage'
go

sp_addextendedproc 'xp_updatelineage', 'xprepl.dll'
go

grant exec on xp_updatelineage to public
go

if exists (select * from sysobjects
		where name = 'xp_proxiedmetadata')
	execute dbo.sp_dropextendedproc 'xp_proxiedmetadata'
go

sp_addextendedproc 'xp_proxiedmetadata', 'xprepl.dll'
go

grant exec on xp_proxiedmetadata to public
go

if exists (select * from sysobjects
		where name = 'xp_initcolvs')
	execute dbo.sp_dropextendedproc 'xp_initcolvs'
go

sp_addextendedproc 'xp_initcolvs', 'xprepl.dll'
go
grant exec on xp_initcolvs to public
go

if exists (select * from sysobjects
		where name = 'xp_updatecolvbm')
	execute dbo.sp_dropextendedproc 'xp_updatecolvbm'
go

sp_addextendedproc 'xp_updatecolvbm', 'xprepl.dll'
go

grant exec on xp_updatecolvbm to public
go

if exists (select * from sysobjects
		where name = 'xp_showcolv')
	execute dbo.sp_dropextendedproc 'xp_showcolv'
go

sp_addextendedproc 'xp_showcolv', 'xprepl.dll'
go

grant exec on xp_showcolv to public
go

if exists (select * from sysobjects
		where name = 'xp_execresultset')
	execute dbo.sp_dropextendedproc 'xp_execresultset'
go

sp_addextendedproc 'xp_execresultset', 'xprepl.dll'
go

grant exec on xp_execresultset to public
go

if exists (select * from sysobjects
		where name = 'xp_varbintohexstr')
	execute dbo.sp_dropextendedproc 'xp_varbintohexstr'
go

sp_addextendedproc 'xp_varbintohexstr', 'xprepl.dll'
go

grant exec on xp_varbintohexstr to public
go

if exists (select * from sysobjects
		where name = 'xp_intersectbitmaps')
	execute dbo.sp_dropextendedproc 'xp_intersectbitmaps'
go

sp_addextendedproc 'xp_intersectbitmaps', 'xprepl.dll'
go

grant exec on xp_intersectbitmaps to public
go

if exists (select * from sysobjects
		where name = 'xp_displayparamstmt')
	execute dbo.sp_dropextendedproc 'xp_displayparamstmt'
go

sp_addextendedproc 'xp_displayparamstmt', 'xprepl.dll'
go

grant exec on xp_displayparamstmt to public
go


if exists (select * from sysobjects
		where name = 'xp_printstatements')
	execute dbo.sp_dropextendedproc 'xp_printstatements'
go

sp_addextendedproc 'xp_printstatements', 'xprepl.dll'
go

grant exec on xp_printstatements to public
go




/* Create table dbo.MSreplication_options */
IF NOT EXISTS (SELECT * FROM sysobjects WHERE name = 'MSreplication_options'
	and type = 'U')
BEGIN
	raiserror('Creating procedure Creating table MSreplication_options',0,1)
	

	CREATE TABLE dbo.MSreplication_options 
	(
	optname			sysname NOT NULL,
	value			bit NOT NULL,
	major_version	int NOT NULL,
	minor_version	int NOT NULL,
	revision		int NOT NULL,
	install_failures int NOT NULL
	)
END
GO

IF NOT EXISTS (SELECT * FROM MSreplication_options WHERE optname = 'transactional')
	INSERT INTO MSreplication_options VALUES
		('transactional',0,0,0,0,0)
IF NOT EXISTS (SELECT * FROM MSreplication_options WHERE optname = 'merge')
	INSERT INTO MSreplication_options VALUES
		('merge',0,0,0,0,0)
GO

raiserror('Creating procedure sp_MSreplcheck_name', 0,1)
GO

CREATE PROCEDURE sp_MSreplcheck_name
	@name			sysname,
	@raise_error	bit = 1
AS
	declare @index	int

	Set nocount on

	-- Name cannot be NULL or empty ("")
	-- Blank identifiers (" ") are allowed
	IF (@name is null OR datalength(@name) = 0)
	begin
		if @raise_error = 1
			raiserror (15004,16,-1)
		return (1)
	end

	-- Check for proscribed characters

	declare @length int
	select @length = datalength( @name ) / 2
	select @index = 1
	while @index < @length
	begin
		if( 0 = unicode( substring( @name, @index, 1 ) ) )
		begin
			if @raise_error = 1
				raiserror(15006,16,-1,@name)
			return (1)
		end

		select @index = @index + 1
	end

	--check for other proscribed characters

	select @index = charindex( N'%', @name)
	if (@index <> 0)
	begin
		if @raise_error = 1
			raiserror(15006,16,-1,@name)
		return (1)
	end
	select @index = charindex(N'*', @name)
	if (@index <> 0)
	begin
		if @raise_error = 1
			raiserror(15006,16,-1,@name)
		return (1)
	end
	select @index = charindex(N'[', @name)
	if (@index <> 0)
	begin
		if @raise_error = 1
			raiserror(15006,16,-1,@name)
		return (1)
	end
	select @index = charindex(N']', @name)
	if (@index <> 0)
	begin
		if @raise_error = 1
			raiserror(15006,16,-1,@name)
		return (1)
	end
	select @index = charindex(N'|', @name)
	if (@index <> 0)
	begin
		if @raise_error = 1
			raiserror(15006,16,-1,@name)
		return (1)
	end
	select @index = charindex(N':', @name)
	if (@index <> 0)
	begin
		if @raise_error = 1
			raiserror(15006,16,-1,@name)
		return (1)
	end
	select @index = charindex(N'"', @name)
	if (@index <> 0)
	begin
		if @raise_error = 1
			raiserror(15006,16,-1,@name)
		return (1)
	end
	select @index = charindex(N'?', @name)
	if (@index <> 0)
	begin
		if @raise_error = 1
			raiserror(15006,16,-1,@name)
		return (1)
	end
	select @index = charindex(N'''', @name)
	if (@index <> 0)
	begin
		if @raise_error = 1
			raiserror(15006,16,-1,@name)
		return (1)
	end
	select @index = charindex(N'\', @name)
	if (@index <> 0)
	begin
		if @raise_error = 1
			raiserror(15006,16,-1,@name)
		return (1)
	end
	select @index = charindex(N'/', @name)
	if (@index <> 0)
	begin
		if @raise_error = 1
			raiserror(15006,16,-1,@name)
		return (1)
	end
	select @index = charindex(N'<', @name)
	if (@index <> 0)
	begin
		if @raise_error = 1
			raiserror(15006,16,-1,@name)
		return (1)
	end
	select @index = charindex(N'>', @name)
	if (@index <> 0)
	begin
		if @raise_error = 1
			raiserror(15006,16,-1,@name)
		return (1)
	end
	
	-- return success

	return (0) 
GO
    

exec dbo.sp_MS_marksystemobject sp_MSreplcheck_name
go



raiserror('Creating procedure sp_MScheckvalidsystables', 0,1)
GO

create procedure sp_MScheckvalidsystables  @validsubs int output
AS
	if not exists (select name from sysobjects where name='sysmergesubscriptions')
		begin
		set @validsubs = 0
		return
		end

	/* Is there a valid non-loopback subscription? */
	if exists (select * from sysmergesubscriptions
		where db_name=db_name() and srvid = (select srvid from master..sysservers where UPPER(srvname) = UPPER(@@servername))
		and subid <> partnerid)
		begin
		set @validsubs = 1
		return
		end
	/* Only possible subscriptions are loopbacks.  If database not enabled for publishing,
	** then they don't indicate a valid publication/subscription. */
	if not exists (select name from master..sysdatabases where
		(category & 4) = 4 and name = db_name())
		begin
		set @validsubs = 0
		return
		end
	/* Database has merge publishing turned on, is probably a publisher.  Look for loopback
	** subscription just to be sure... */
	if exists (select * from sysmergesubscriptions
		where db_name=db_name() and srvid = (select srvid from master..sysservers where UPPER(srvname) = UPPER(@@servername)))
		begin
		set @validsubs = 1
		return
		end
		
	/* Must not be valid... */	
	set @validsubs = 0
	return


GO


raiserror('Creating procedure sp_MSdrop_mergesystables', 0,1)
GO
create procedure sp_MSdrop_mergesystables as

	begin tran
	save transaction drop_mergesystables
	if exists (select * from sysobjects
		where name = 'sysmergearticles')
		begin
		drop table sysmergearticles
		end
	if @@error<>0
		goto Error

	if exists (select * from sysobjects
		where name = 'sysmergepublications')
		begin
		drop table sysmergepublications
		end
	if @@error<>0
		goto Error

	if exists (select * from sysobjects
		where name = 'sysmergesubscriptions')
		begin
		drop table sysmergesubscriptions
		end
	if @@error<>0
		goto Error
		
	if exists (select * from sysobjects
		where name = 'MSmerge_contents')
		begin
		drop table MSmerge_contents
		end
	if @@error<>0
		goto Error

	if exists (select * from sysobjects
		where name = 'MSmerge_replinfo')
		begin
		drop table MSmerge_replinfo
		end
	if @@error<>0
		goto Error
		
	if exists (select * from sysobjects
		where name = 'MSmerge_tombstone')
		begin
		drop table MSmerge_tombstone
		end
	if @@error<>0
		goto Error
		
	if exists (select * from sysobjects
		where name = 'MSmerge_genhistory')
		begin
		drop table MSmerge_genhistory
		end
	if @@error<>0
		goto Error
		
	if exists (select * from sysobjects
		where name = 'MSmerge_delete_conflicts')
		begin
		drop table MSmerge_delete_conflicts
		end
	if @@error<>0
		goto Error

	if exists (select * from sysobjects
		where name = 'sysmergeschemachange')
		begin
		drop table sysmergeschemachange
		end
	if @@error<>0
		goto Error

	if exists (select * from sysobjects
		where name = 'sysmergesubsetfilters')
		begin
		drop table sysmergesubsetfilters
		end
	if @@error<>0
		goto Error

	commit transaction	
	return 0
Error:
	RAISERROR (20007, 16, -1)
	if @@trancount > 0
	begin
		ROLLBACK TRANSACTION drop_mergesystables
		COMMIT TRANSACTION
	end
	return 1
go

exec dbo.sp_MS_marksystemobject sp_MSdrop_mergesystables
go

raiserror ('Executing procedure dbo.sp_MSdrop_mergesystables.',0,1)
go
exec dbo.sp_MSdrop_mergesystables
go

dump tran master with no_log
go

raiserror('Creating procedure sp_MScreate_mergesystables',0,1)
GO
create procedure sp_MScreate_mergesystables as

	/* This is to make sure that the varbinary columns do not get padded */

	set ANSI_PADDING off

	DECLARE @exist bit 
	DECLARE @validsubs  int
	select @exist = 1
	
	begin tran
	save transaction MScreate_mergesystables

	exec dbo.sp_MScheckvalidsystables  @validsubs  output
	if @validsubs = 0
		exec dbo.sp_MSdrop_mergesystables
		
	if not exists (select * from sysobjects where name = 'sysmergepublications')
		begin

			raiserror('Creating table sysmergepublications',0,1)
			
			create table dbo.sysmergepublications
			(	publisher				sysname NOT NULL default @@servername,
				publisher_db			sysname NOT NULL default db_name(),
				name					sysname				NOT NULL,
				description				nvarchar(255) 		NULL,
				retention				int					NULL,
				publication_type 		tinyint				NULL,
				pubid 					uniqueidentifier 	NOT NULL,
				designmasterid			uniqueidentifier 	NULL,
				parentid				uniqueidentifier 	NULL,
				sync_mode				tinyint				NULL,
				allow_push				int					NULL,
				allow_pull				int					NULL,
				allow_anonymous			int					NULL,
				centralized_conflicts	int					NULL,
				status					tinyint				NULL,
				snapshot_ready			tinyint				NULL,
		        enabled_for_internet    bit                	NOT NULL default 0,
				dynamic_filters			bit					NOT NULL default 0
			)
			if @@ERROR <> 0
				goto Error
			exec dbo.sp_MS_marksystemobject sysmergepublications
			if @@ERROR <> 0
				goto Error
			grant select on sysmergepublications to public
		end


	if not exists (select * from sysobjects where name = 'sysmergearticles')
		begin
		
			raiserror('Creating table sysmergearticles',0,1)

			
			create table dbo.sysmergearticles (
				name					sysname				NOT NULL,
		        type        			tinyint       	 	NULL,
				objid					int					NOT NULL,
				sync_objid				int					NOT NULL,
				view_type 				tinyint				NULL,
				artid					uniqueidentifier	NOT NULL,
				description    			nvarchar(255)    	NULL,
				pre_creation_command	tinyint				NULL,
				pubid					uniqueidentifier 	NOT NULL,
				nickname				int					NOT NULL,
				column_tracking			int					NOT NULL,
				status					tinyint				NULL,
				conflict_table			sysname				NULL,
				creation_script			nvarchar(255)		NULL,
				conflict_script			nvarchar(255)		NULL,
				article_resolver		nvarchar(255)		NULL,
				ins_conflict_proc		sysname				NULL,
				insert_proc				sysname				NULL,
				update_proc				sysname				NULL,
				select_proc				sysname				NULL,
		        schema_option 			binary(8) 			NULL,
				destination_object		sysname				NOT NULL,
				resolver_clsid			nvarchar(50)		NULL,
				subset_filterclause    	nvarchar(1000)  	NULL,
				missing_col_count		int					NULL,
				missing_cols			varbinary(128)		NULL,
				columns        			varbinary(128)   	NULL,
				resolver_info			nvarchar(255)		NULL,
				view_sel_proc			nvarchar(290)		NULL,
				gen_cur					int					NULL
			)
		
			if @@error<>0
				goto Error
			else
				begin
					create unique clustered index uc1sysmergearticles
						on sysmergearticles(artid, pubid) 
					if @@ERROR <> 0
						goto Error
				end
			exec dbo.sp_MS_marksystemobject sysmergearticles
			if @@ERROR <> 0
				goto Error
			grant select on sysmergearticles to public
			
		end

	if not exists (select * from sysobjects	where name = 'sysmergesubscriptions')
		begin
		
			raiserror('Creating table sysmergesubscriptions',0,1)

			
			create table dbo.sysmergesubscriptions
			(
				subid     			uniqueidentifier 	NOT NULL,
				partnerid 			uniqueidentifier 	NOT NULL,
				datasource_type		int					NOT NULL,
				datasource_path		nvarchar(255)		NULL,
				srvid	     		int					NOT NULL,
				db_name		  		sysname		 		NOT NULL
				constraint 			unique_pubsrvdb 	unique nonclustered (pubid, srvid, db_name),
				pubid				uniqueidentifier 	NULL,
				status    			tinyint     		NOT NULL,
				subscriber_type		int					NOT NULL,
				subscription_type	int					NOT NULL,
				priority			real				NOT NULL,
				sync_type 			tinyint				NOT NULL,	-- 1 = automatic 2 = no sync
				description			nvarchar(255)		NULL,
				login_name			sysname				NOT NULL,
				last_validated		datetime			NULL
			)
		
			if @@error<>0
				goto Error
			else
				begin
					create unique clustered index uc1sysmergesubscriptions 
						on sysmergesubscriptions (subid) 
					if @@ERROR<>0
						goto Error
				end
			exec dbo.sp_MS_marksystemobject sysmergesubscriptions
			if @@ERROR <> 0
				goto Error
			grant select on sysmergesubscriptions to public
			
		end

	if not exists (select * from sysobjects	where name = 'MSmerge_replinfo')
		begin
			raiserror('Creating table MSmerge_replinfo',0,1)
			
			create table dbo.MSmerge_replinfo
			(
				repid     				uniqueidentifier 	NOT NULL,
				replnickname			int					NOT NULL,
				recgen					int     			NULL,
				recguid					uniqueidentifier 	NULL,
				sentgen					int     			NULL,
				sentguid				uniqueidentifier 	NULL,
				schemaversion			int     			NULL,
				schemaguid				uniqueidentifier 	NULL,
				merge_jobid				binary(16)			NULL,
				snapshot_jobid			binary(16)			NULL
			)
		
			if @@ERROR <> 0
				goto Error
			else
				begin
					create unique clustered index uc1MSmerge_replinfo
						on MSmerge_replinfo (repid)
					if @@ERROR <> 0
						goto Error
				end
			exec dbo.sp_MS_marksystemobject MSmerge_replinfo
			if @@ERROR <> 0
				goto Error
			grant select on MSmerge_replinfo to public
			
		end

	if not exists (select * from sysobjects	where name = 'MSmerge_tombstone')
		begin
			raiserror('Creating table MSmerge_tombstone',0,1)
			
			create table dbo.MSmerge_tombstone
			(
				rowguid			uniqueidentifier rowguidcol NOT NULL,
				tablenick		int				NOT NULL,
				type			tinyint			NOT NULL,
				lineage			varbinary(255)	NOT NULL,
				generation		int				NOT NULL,
				reason			nvarchar(255)	NOT NULL,
			)

			if @@ERROR <> 0
				goto Error
			else
				begin
					create unique clustered index uc1MSmerge_tombstone
						on MSmerge_tombstone (tablenick, rowguid) 
					if @@ERROR <> 0
						goto Error
					create index nc2MSmerge_tombstone
						on MSmerge_tombstone (generation) 
					if @@ERROR <> 0
						goto Error
				end	
			 exec dbo.sp_MS_marksystemobject MSmerge_tombstone
			 if @@ERROR <> 0
				goto Error
			grant select on MSmerge_tombstone to public
			
		end

	if not exists (select * from sysobjects	where name = 'MSmerge_contents')
		begin
			raiserror('Creating table MSmerge_contents',0,1)
			
			create table dbo.MSmerge_contents
			(
				tablenick		int					NOT NULL,
				rowguid			uniqueidentifier rowguidcol   NOT NULL,
				generation		int					NOT NULL,
				partchangegen	int					NULL,
				joinchangegen	int					NULL,
				lineage			varbinary(249)		NOT NULL,
				colv1			varbinary(2048)		NULL,
			)
		
			if @@ERROR <> 0
				goto Error
			else
				begin
					create unique clustered index uc1SycContents on MSmerge_contents( tablenick, rowguid )
					if @@ERROR <> 0
						goto Error
					create index nc2MSmerge_contents on MSmerge_contents(tablenick, generation) 
					if @@ERROR <> 0
						goto Error
				end
			exec dbo.sp_MS_marksystemobject MSmerge_contents
			if @@ERROR <> 0
				goto Error
			grant select on MSmerge_contents to public
			
		end				

	if not exists (select * from sysobjects	where name = 'MSmerge_genhistory')
		begin
			raiserror('Creating table MSmerge_genhistory',0,1)
			
			create table dbo.MSmerge_genhistory
			(
				guidsrc 		uniqueidentifier 	NOT NULL,
				guidlocal 		uniqueidentifier 	NOT NULL,
				pubid			uniqueidentifier 	NULL,
				generation 		int					NOT NULL,
				art_nick		int					NULL,
				nicknames		varbinary(255)		NOT NULL,
				coldate 		datetime			NOT NULL
			)
		
			if @@ERROR <> 0
				goto Error
			create clustered index uc1MSmerge_genhistory on MSmerge_genhistory(guidsrc) 
			if @@ERROR <> 0
				goto Error

			create  index nc1MSmerge_genhistory on MSmerge_genhistory(generation) 
			if @@ERROR <> 0
				goto Error

			create  index nc2MSmerge_genhistory on MSmerge_genhistory(guidlocal) 
			if @@ERROR <> 0
				goto Error

			 exec dbo.sp_MS_marksystemobject MSmerge_genhistory
			 if @@ERROR <> 0
				goto Error
			grant select on MSmerge_genhistory to public
			
		end

	if not exists (select * from sysobjects	where name = 'MSmerge_delete_conflicts')
		begin

			raiserror('Creating table MSmerge_delete_conflicts',0,1)
			
			create table dbo.MSmerge_delete_conflicts
			(
				tablenick			int				NOT NULL,
				rowguid				uniqueidentifier rowguidcol NOT NULL,
				origin_datasource	nvarchar(255)	NULL,
				conflict_type		int NULL,
				reason_code			int NULL,
				reason_text			nvarchar(720) 	NULL,
				pubid				uniqueidentifier NULL
			)
		
			if @@ERROR <> 0
				goto Error
			else
				begin
					create clustered index uc1MSmerge_delete_conflicts on MSmerge_delete_conflicts(tablenick, rowguid) 
					if @@ERROR <> 0
						goto Error
				end					
			exec dbo.sp_MS_marksystemobject MSmerge_delete_conflicts
			if @@ERROR <> 0
				goto Error
			grant select on MSmerge_delete_conflicts to public
			
		end

	if not exists (select * from sysobjects	where name = 'sysmergeschemachange')
		begin
		
			raiserror('Creating table sysmergeschemachange',0,1)
			
			create table dbo.sysmergeschemachange
			(
				pubid			uniqueidentifier 	NOT NULL,
				artid			uniqueidentifier 	NULL,
				schemaversion 	int 	   		NOT NULL,
				schemaguid    	uniqueidentifier 	NOT NULL,
				schematype		int		  		NOT NULL,
				schematext		nvarchar(2000) 	NOT NULL
			)
		
			if @@ERROR <> 0
				goto Error
			else
				begin
					create clustered index schemachangeversion on sysmergeschemachange(schemaversion) 
					if @@ERROR <> 0
						goto Error
				end
			exec dbo.sp_MS_marksystemobject sysmergeschemachange
			if @@ERROR <> 0
				goto Error
			grant select on sysmergeschemachange to public
			
		end

	if not exists (select * from sysobjects where name = 'sysmergesubsetfilters')
		begin
			raiserror('Creating table sysmergesubsetfilters',0,1)

			
			create table dbo.sysmergesubsetfilters (
                filtername              sysname		         NOT NULL,
                join_filterid			int					identity NOT NULL,
				pubid					uniqueidentifier	NOT NULL,
				artid					uniqueidentifier	NOT NULL,
				art_nickname			int					NOT NULL,
				join_articlename		sysname NOT NULL,
				join_nickname 			int					NOT NULL,
				join_unique_key			int					NOT NULL,
				expand_proc				sysname					NULL,
				join_filterclause    	nvarchar(1000)  		NULL
			)
			if @@ERROR <> 0
				goto Error
			exec dbo.sp_MS_marksystemobject sysmergesubsetfilters
			if @@ERROR <> 0
				goto Error
			grant select on sysmergesubsetfilters to public
			
		end

		if @@error <> 0
			return(1)

	commit transaction
	return (0)
Error:
	if @@trancount > 0
	begin
		ROLLBACK TRANSACTION MScreate_mergesystables
		COMMIT TRANSACTION
	end
	RAISERROR (20008, 16, -1)
	return (1)
go

exec dbo.sp_MS_marksystemobject sp_MScreate_mergesystables 
go

raiserror('Creating procedure sp_MStestbit',0,1)
go
create procedure sp_MStestbit
			@bm varbinary(125),
			@coltotest smallint
AS
			declare @word smallint
			declare @bit  smallint
			declare @mask binary(2)
			declare @mval int
			declare @oldword binary(2)  

			if @coltotest < 1 return 0

			SELECT @word = CONVERT(smallint, 1 + FLOOR((@coltotest -1)/16))

			SELECT @bit = (@coltotest -1) % 16

			SELECT @mval = POWER(2, @bit)
			SELECT @mask = convert( binary(2), unicode( substring( convert( nchar(2), convert( binary(4), @mval ) ), 2, 1 ) ) )
			
			SELECT @oldword = convert( binary(2), SUBSTRING( convert( nvarchar(63),@bm), @word, 1) )
			IF @oldword IS NULL return 0

			return  convert( smallint, @oldword ) & convert( smallint, @mask )
go
exec dbo.sp_MS_marksystemobject sp_MStestbit
go
		
		
raiserror('Creating procedure sp_MSsetbit',0,1)
go
create procedure sp_MSsetbit
				@bm varbinary(125) output,
				@coltoadd smallint
AS
			declare @word smallint
			declare @bit smallint
			declare @mask binary(2)
			declare @mval int
			declare @newword binary(2)     
			declare @oldword binary(2) 

			SELECT @word = CONVERT(smallint, 1 + FLOOR((@coltoadd-1)/16))

			IF @word > 62 return 0

			SELECT @bit = (@coltoadd-1) % 16

			SET @mval = POWER(2, @bit)
			SELECT @mask = convert( binary(2), unicode( substring( convert( nchar(2), convert( binary(4), @mval ) ), 2, 1 ) ) )

			if @bm is null
				set @bm = 0x0
			while datalength(@bm) < @word * 2
				set @bm = @bm + 0x0000

			SET @oldword = convert( binary(2), SUBSTRING( convert(nvarchar(63),@bm), @word, 1) )
			IF @oldword IS NULL SET @oldword = 0x00

			SET @newword = convert( smallint, @oldword) | convert( smallint, @mask )

			SET @bm = CONVERT(varbinary(125), STUFF( CONVERT(nvarchar(63),@bm), @word, 1, convert( nchar(1),@newword)) )
go			
exec dbo.sp_MS_marksystemobject sp_MSsetbit
go

raiserror('Creating procedure sp_MSinsertcontents',0,1)
go
create procedure sp_MSinsertcontents
				@tablenick int,
				@rowguid uniqueidentifier,
	 			@lineage varbinary(249),
	 			@colv1 varbinary(2048)
AS
				/*
				** permission check
				*/
				declare @retcode	int
				declare @objid		int
				declare @owner		sysname
				declare @artid		uniqueidentifier
				declare @guidstr	nvarchar(32)	
				declare @instrigger	sysname
				
				select @objid = objid, @artid=artid from sysmergearticles where nickname=@tablenick
				select @owner =user_name(uid) from sysobjects where id=@objid

				exec @retcode=sp_MSguidtostr @artid, @guidstr out
					if @retcode<>0 or @@ERROR<>0 return (1)

				set @instrigger = @owner + '.ins_' + @guidstr

				if trigger_nestlevel(object_id(@instrigger)) = 0
				begin
					raiserror(14126, 16, -1)
					return (1) -- current user does not have insert permission to underlying table
				end
			
				insert into MSmerge_contents (tablenick, rowguid, generation, partchangegen, joinchangegen, lineage, colv1)
					values (@tablenick, @rowguid, 0, 0, 0, @lineage, @colv1)
				if @@error <> 0
					begin
					raiserror (20041, 16, -1)
					return (1)
					end			

				delete from MSmerge_tombstone where rowguid = @rowguid and tablenick = @tablenick		 
				if @@error <> 0
					begin
					raiserror (20041, 16, -1)
					return (1)
					end	

go
exec dbo.sp_MS_marksystemobject sp_MSinsertcontents
go
grant exec on dbo.sp_MSinsertcontents to public

raiserror('Creating procedure sp_MSupdatecontents',0,1)
go
create procedure sp_MSupdatecontents
				 @tablenick int,
				 @rowguid uniqueidentifier,
				 @lineage varbinary(249),
				 @colv1 varbinary(2048),
				 @partchange int = null,
				 @joinchange int = null
AS
			/*
			** permission check
			*/
			declare @retcode	int
			declare @objid		int
			declare @owner		sysname
			declare @artid		uniqueidentifier
			declare @guidstr	nvarchar(32)	
			declare @updtrigger	sysname
			
			select @objid = objid, @artid=artid from sysmergearticles where nickname=@tablenick
			select @owner =user_name(uid) from sysobjects where id=@objid
			
			exec @retcode=sp_MSguidtostr @artid, @guidstr out
					if @retcode<>0 or @@ERROR<>0 return (1)
					
				set @updtrigger = @owner + '.upd_' + @guidstr

				if trigger_nestlevel(object_id(@updtrigger)) = 0
				begin
					raiserror(14126, 16, -1)
					return (1) -- current user does not 'update all' permission upon underlying table
				end
			
			update MSmerge_contents set lineage = @lineage, generation = 0, colv1 = @colv1
				where tablenick = @tablenick and rowguid = @rowguid
			if (@@rowcount = 0)
				insert into MSmerge_contents (tablenick, rowguid, generation, joinchangegen, lineage, colv1)
					values (@tablenick, @rowguid, 0, 1, @lineage, @colv1)
			if @@error <> 0
				begin
				raiserror (20041, 16, -1)
				return (1)
				end
			if @partchange = 1
				begin
				update MSmerge_contents set partchangegen = 0, joinchangegen = 0
					where tablenick = @tablenick and rowguid = @rowguid
				if @@error <> 0
					begin
					raiserror (20041, 16, -1)
					return (1)
					end
				end
			else if @joinchange = 1
				begin
				update MSmerge_contents set joinchangegen = 0
					where tablenick = @tablenick and rowguid = @rowguid
				if @@error <> 0
					begin
					raiserror (20041, 16, -1)
					return (1)
					end
				end 
go
exec dbo.sp_MS_marksystemobject sp_MSupdatecontents
go
grant exec on dbo.sp_MSupdatecontents to public

raiserror(15339, -1, -1, 'sp_MSdeletecontents')
go
create procedure sp_MSdeletecontents
				 @tablenick int,
				 @rowguid uniqueidentifier
AS
				declare @nick int
				declare @reason nvarchar(255)
				declare @lineage varbinary(255)

				/*
				** permission check
				*/
				declare @retcode	int
				declare @objid		int
				declare @owner		sysname
				declare @artid		uniqueidentifier
				declare @guidstr	nvarchar(32)	
				declare @deltrigger	sysname
				
				select @objid = objid, @artid=artid from sysmergearticles where nickname=@tablenick
				select @owner =user_name(uid) from sysobjects where id=@objid
				
				exec @retcode=sp_MSguidtostr @artid, @guidstr out
					if @retcode<>0 or @@ERROR<>0 return (1)

				set @deltrigger = @owner + '.del_' + @guidstr

				if trigger_nestlevel(object_id(@deltrigger)) = 0
					begin
						raiserror(14126, 16, -1)
						return (1) -- current user does not have 'delete' permission to underlying table
					end
			
				exec dbo.sp_MSgetreplnick @nickname = @nick out
				if (@@error <> 0) or @nick IS NULL 
			        begin
		            RAISERROR (14055, 11, -1)
		            RETURN(1)
			        end                 

				select @lineage = lineage from MSmerge_contents (UPDLOCK ROWLOCK index = 1) 
					where tablenick = @tablenick and rowguid = @rowguid
				exec master..xp_updatelineage @lineage output, @nick
				select @reason = 'user delete'
	
				insert into MSmerge_tombstone (rowguid, tablenick, type, lineage, generation, reason)
					values (@rowguid, @tablenick, 1, @lineage, 0, @reason)
				if @@error <> 0
					begin
					raiserror (20041, 16, -1)
					return (1)
					end
				delete from MSmerge_contents where
					tablenick = @tablenick and rowguid = @rowguid
				if @@error <> 0
					begin
					raiserror (20041, 16, -1)
					return (1)
					end 
go
exec dbo.sp_MS_marksystemobject sp_MSdeletecontents
go		
grant exec on dbo.sp_MSdeletecontents to public


raiserror('Creating procedure sp_MSunmarkifneeded',0,1)
GO

CREATE PROCEDURE sp_MSunmarkifneeded(
@object			sysname,
@pubid			uniqueidentifier
)AS
declare @table_in_use	int
declare @retcode 		int

select @table_in_use = 0
if EXISTS (select * from sysmergearticles where pubid<>@pubid and objid=object_id(@object))
	begin
		select @table_in_use = 1
		select @table_in_use
		return (0)
	end
exec @retcode = sp_MSunmarkreplinfo @object
if @retcode <>0 or @@error<>0
	return (1)
select @table_in_use 
return (0)
GO
exec dbo.sp_MS_marksystemobject sp_MSunmarkifneeded
go		
grant exec on dbo.sp_MSunmarkifneeded to public
go

raiserror('Creating procedure sp_MSunmarkreplinfo',0,1)
GO

CREATE PROCEDURE sp_MSunmarkreplinfo(
	@object				sysname,			/* Name of the table, unqualitied */
	@owner				sysname = NULL,			/* Name of the owner, unqualified */
	@type				smallint = 0        /* default is to unmark, as name implies */
)AS
declare @merge_pub_object_bit int
declare @merge_pub_unmark_bit int
declare @id	int
declare @qualified_name			nvarchar(258)


if @owner is NULL or @owner=''
	select @owner = user_name(uid) from sysobjects where id = object_id(QUOTENAME(@object))
select @qualified_name = QUOTENAME(@owner) + '.' + QUOTENAME(@object) 


select @id = object_id(@qualified_name)

select @merge_pub_object_bit 	= 128
select @merge_pub_unmark_bit = ~@merge_pub_object_bit

if exists (select name from sysobjects where id = @id) 
	begin
			if @type = 0    /* type = 0, unmark; else mark the bit */
		begin
			BEGIN TRANSACTION
   				exec dbo.sp_replupdateschema @qualified_name
       			update sysobjects set replinfo = replinfo & @merge_pub_unmark_bit where id = @id
	    	COMMIT TRANSACTION
	    end
	    	else
	    begin
	    	BEGIN TRANSACTION
	    		exec dbo.sp_replupdateschema @qualified_name
       			update sysobjects set replinfo = replinfo | @merge_pub_object_bit where id = @id
       		COMMIT TRANSACTION
		end
	end
GO
exec dbo.sp_MS_marksystemobject sp_MSunmarkreplinfo
go
grant execute on dbo.sp_MSunmarkreplinfo to public

raiserror('Creating procedure sp_MSaddanonymousreplica',0,1)
GO
CREATE PROCEDURE sp_MSaddanonymousreplica
	(@publication 		sysname,
	 @publisher			sysname,
	 @publisherDB		sysname,
	 @anonymous			int
)
as
declare @retcode 				int
declare @subscription_type 		nvarchar(15)

if exists (select * from sysobjects where name='sysmergepublications')
begin
	IF EXISTS (select name from sysmergepublications where name=@publication and UPPER(publisher)=UPPER(@publisher) and publisher_db = @publisherDB)
		return (0)   -- replica exists. 
				-- else call this SP to add this replica
end

if @anonymous = 1 select @subscription_type = 'anonymous'
	else select @subscription_type = 'local'
				
exec @retcode = dbo.sp_addmergepullsubscription 
	@publication = @publication,
	@publisher = @publisher,
	@publisher_db=@publisherDB,
	@subscriber_type =@subscription_type

IF @retcode<>0 or @@ERROR<>0 return (1)
return (0)
GO
exec dbo.sp_MS_marksystemobject sp_MSaddanonymousreplica
go
grant execute on dbo.sp_MSaddanonymousreplica to public
go 

raiserror('Creating procedure sp_MSgetreplicainfo',0,1)
GO
CREATE PROCEDURE sp_MSgetreplicainfo
	(@publisher			sysname,
	 @publisher_db		sysname,
	 @publication 		sysname,
	 @datasource_type	int = 0, 				/* 0 = SQL Server, 1 = DSN, 2 = Jet */
	 @server_name		sysname	= NULL, 		/* Server Name */
	 @db_name			sysname = NULL, 		/* Database Name */
	 @datasource_path	nvarchar(255) = NULL)	/* Datasource path - JET MDB file path etc */
	 
as
	declare		@srvid				int
	declare		@retcode			int
	declare		@repid 				uniqueidentifier
	declare		@pubid 				uniqueidentifier
	declare		@schemaguid			uniqueidentifier
	declare  	@nickname 			int
	declare 	@subscription_type int
	declare 	@reptype 			tinyint
	declare 	@priority 			real 
	declare 	@schversion 		int 
	declare 	@status				int
	declare  	@partnerid 			uniqueidentifier
	declare 	@sync_type 			tinyint
	declare 	@description 		nvarchar(255)

    /*
    ** Parameter Check:  @publication.
    ** Make sure that the publication exists.
    */
	if (@publication is null)
		begin
		RAISERROR(14043, 16, -1, '@publication')
		return (1)
		end

	if (@server_name is NULL)
		SET @server_name = @@SERVERNAME

	if (@db_name is NULL)
		set @db_name = db_name()
		
	SELECT @srvid = srvid FROM master..sysservers WHERE UPPER(srvname) = UPPER(@server_name)
   	IF @@ERROR <> 0
       	BEGIN
            RAISERROR (14080, 16, -1)
     		RETURN (1)
		END

    IF @srvid IS NULL
        BEGIN
            RAISERROR (14010, 16, -1)
            RETURN (1)
        END

	select @pubid = pubid from sysmergepublications 
		where name = @publication and UPPER(publisher)=UPPER(@publisher) and publisher_db=@publisher_db
	if (@pubid is null)
		begin
			RAISERROR (20026, 16, -1, @publication)
			return (1)
		end

	if (@datasource_type = 0)
		begin
			SELECT @repid = subid, @priority = priority, @reptype = subscriber_type, 
				@subscription_type = subscription_type , @status = status, 
				@partnerid = partnerid, @sync_type = sync_type, @description = description FROM sysmergesubscriptions
				WHERE srvid = @srvid and db_name = @db_name and pubid = @pubid
		END
	ELSE
		BEGIN
			SELECT @repid = subid, @priority = priority, @reptype = subscriber_type, 
				@subscription_type = subscription_type , @status = status, 
				@partnerid = partnerid, @sync_type = sync_type, @description = description FROM sysmergesubscriptions
				WHERE srvid = @srvid and pubid = @pubid
		END

	if @repid is NULL
		begin
			RAISERROR(20021, 16, -1)
			return (1)
		end
	select @schversion = schemaversion, @schemaguid = schemaguid from MSmerge_replinfo where repid = @repid
	select @nickname = replnickname from MSmerge_replinfo where repid = @repid
	select @repid, @nickname, @reptype, @subscription_type, @priority, @schversion, @schemaguid,
		@status, @partnerid, @sync_type, @description

	return (0)
go
exec dbo.sp_MS_marksystemobject sp_MSgetreplicainfo
go
grant execute on dbo.sp_MSgetreplicainfo to public


raiserror('Creating procedure sp_MSadd_repl_job',0,1)
go

CREATE PROCEDURE sp_MSadd_repl_job
  @name                   nvarchar(200),
  @subsystem              nvarchar(60)  = 'TSQL',
  @server                 sysname  = NULL,
  @username               sysname  = NULL,
  @databasename           sysname  = NULL,
  @enabled                TINYINT      = 0,
  @freqtype               INT          = 2, -- 2 means OnDemand
  @freqinterval           INT          = 1,
  @freqsubtype            INT          = 1,
  @freqsubinterval        INT          = 1,
  @freqrelativeinterval   INT          = 1,
  @freqrecurrencefactor   INT          = 1,
  @activestartdate        INT          = 0,
  @activeenddate          INT          = 0,
  @activestarttimeofday   INT          = 0,
  @activeendtimeofday     INT          = 0,
  @nextrundate            INT          = 0,
  @nextruntime            INT          = 0,
  @runpriority            INT          = 0,
  @emailoperatorname      nvarchar(100) = NULL,
  @retryattempts          INT          = NULL,
  @retrydelay             INT          = 0,
  @command                nvarchar(4000)= NULL,
  @loghistcompletionlevel INT          = 2,
  @emailcompletionlevel   INT          = 0,
  @description            nvarchar(255) = NULL,
  @tagadditionalinfo      nvarchar(96)  = NULL,
  @tagobjectid            INT          = NULL,
  @tagobjecttype          INT          = NULL,
  @cmdexecsuccesscode     INT          = 0,
  @category_name          sysname = NULL, -- New for 7.0
  @failure_detection	  BIT			= 0,
  @agent_id				  INT			= NULL,
  @job_id BINARY(16) = NULL OUTPUT
AS
BEGIN
  DECLARE	@retval INT
  declare	@step_id int
  declare	@step_name nvarchar(100)
  declare	@step_command nvarchar(1024)
  declare	@on_fail_action tinyint
  declare 	@on_success_action tinyint
  declare	@schedule_name nvarchar(100)
  declare	@comments nvarchar(100)

  SET NOCOUNT ON

  SELECT @retval = 1 -- 0 means success, 1 means failure
  set @step_id = 1
  set @on_fail_action = 2	-- Return failure
  set @on_success_action = 1	-- Return success
  set @step_command = NULL

  /*
  ** Set default retries to every minute for 10 minutes.
  **
  */
  if @retryattempts = NULL and @retrydelay = 0
  begin
     select @retryattempts = 10
     select @retrydelay = 1
  end

  BEGIN TRANSACTION

	-- Drop the job if it already exists
	IF EXISTS (SELECT * FROM msdb..sysjobs_view WHERE name = @name)
	begin
		exec @retval = msdb.dbo.sp_delete_job @job_name=@name
		if @@ERROR<>0 or @retval<>0
			goto UNDO
	end

    -- Add the job
    EXECUTE @retval = msdb.dbo.sp_add_job
      @job_name                   = @name,
      @enabled                    = @enabled,
      @start_step_id              = 1,
      @description                = @description,
      @category_name              = @category_name,
      @notify_level_eventlog      = @loghistcompletionlevel,
      @notify_level_email         = @emailcompletionlevel,
      @notify_email_operator_name = @emailoperatorname,
	  @job_id = @job_id OUTPUT

    IF (@retval <> 0)
    BEGIN
		GOTO UNDO
    END

	-- Add startup message step
	if @failure_detection = 1
	begin

		select @step_name = formatmessage(20528)
		select @comments = formatmessage(20529)

		-- Construct command based on subsystem type
		select @step_command =
			case UPPER(@subsystem) 
				WHEN 'SNAPSHOT' THEN
				N'sp_MSadd_snapshot_history @perfmon_increment = 0,  @agent_id = ' + 
					convert (nvarchar(10), @agent_id) + N', @runstatus = 1,  
					@comments = ''' + @comments + ''''
				WHEN 'LOGREADER' THEN
				N'sp_MSadd_logreader_history @perfmon_increment = 0, @agent_id = ' + 
					convert (nvarchar(10), @agent_id) + N', @runstatus = 1, 
					@comments = ''' + @comments + ''''
				WHEN 'DISTRIBUTION' THEN
				N'sp_MSadd_distribution_history @perfmon_increment = 0, @agent_id = ' + 
					convert (nvarchar(10), @agent_id) + N', @runstatus = 1,  
					@comments = ''' + @comments + ''''
				WHEN 'MERGE' THEN
				N'sp_MSadd_merge_history @perfmon_increment = 0, @agent_id = ' + 
					convert (nvarchar(10),@agent_id) + N', @runstatus = 1,  
					@comments = ''' + @comments + ''''
			end
	
		-- Add the job step
		EXECUTE @retval = msdb.dbo.sp_add_jobstep
		  @job_id                = @job_id,
		  @step_id               = @step_id,
		  @step_name             = @step_name,
		  @command               = @step_command,
		  @cmdexec_success_code  = @cmdexecsuccesscode,
		  @on_success_action	 = 3,	-- Goto next step
		  @on_fail_action		 = 3,	-- Goto next step
		  @server                = @server,
		  @database_name         = @databasename,
		  @database_user_name    = @username,
		  @os_run_priority       = @runpriority

		IF (@retval <> 0)
		BEGIN
			GOTO UNDO
		END

		set @step_id = @step_id + 1
		set @on_fail_action = 3			-- Goto next step
	end

    -- Add the job step
 	select @step_name = formatmessage(20530)
    EXECUTE @retval = msdb.dbo.sp_add_jobstep
      @job_id                = @job_id,
      @step_id               = @step_id,
      @step_name             = @step_name,
      @subsystem             = @subsystem,
      @command               = @command,
      @cmdexec_success_code  = @cmdexecsuccesscode,
	  @on_success_action	 = @on_success_action,
	  @on_fail_action		 = @on_fail_action,
	  @server                = @server,
      @database_name         = @databasename,
      @database_user_name    = @username,
      @retry_attempts        = @retryattempts,
      @retry_interval        = @retrydelay,
      @os_run_priority       = @runpriority

    IF (@retval <> 0)
    BEGIN
		GOTO UNDO
    END

	-- Add failure message step
	if @failure_detection = 1
	begin

		set @step_id = @step_id + 1

	 	select @step_name = formatmessage(20531)

		-- Construct command
		select @step_command = N'sp_MSdetect_nonlogged_shutdown @subsystem = ''' + @subsystem +	 N''', @agent_id = ' + convert (nvarchar(10),	@agent_id) 

		-- Add the job step
		EXECUTE @retval = msdb.dbo.sp_add_jobstep
		  @job_id                = @job_id,
		  @step_id               = @step_id,
		  @step_name             = @step_name,
		  @command               = @step_command,
		  @cmdexec_success_code  = @cmdexecsuccesscode,
		  @on_success_action	 = 2,					-- Always quit with failure
		  @server                = @server,
		  @database_name         = @databasename,
		  @database_user_name    = @username,
		  @os_run_priority       = @runpriority

		IF (@retval <> 0)
		BEGIN
			GOTO UNDO
		END
	end

    -- Add the job schedule
    IF (@activestartdate = 0)
      SELECT @activestartdate = NULL
    IF (@activeenddate = 0)
      SELECT @activeenddate = NULL
	
	-- But if @activeenddate is NOT NULL, then @activestartdate cannot be allowed to be NULL either.  Set it to today's date converted to the int format used yyyymmdd

    IF (@activeenddate IS NOT NULL AND @activestartdate IS NULL)
	SELECT @activestartdate=DATEPART(YYYY,getdate()) * 10000 + DATEPART(MM,getdate()) * 100 + DATEPART(DD,getdate())

	-- But never let startdate be > end date
    IF (@activestartdate > @activeenddate)
	SELECT @activestartdate=@activeenddate

    IF (@activestarttimeofday = 0)
      SELECT @activestarttimeofday = NULL
    IF (@activeendtimeofday = 0)
      SELECT @activeendtimeofday = NULL
    IF (@freqtype <> 0x2) -- OnDemand tasks simply have no schedule in 7.0
    BEGIN
	  select @schedule_name = formatmessage(20532)

      EXECUTE @retval = msdb.dbo.sp_add_jobschedule
        @job_id                 = @job_id,
        @name                   = @schedule_name,
        @enabled                = 1,
        @freq_type              = @freqtype,
        @freq_interval          = @freqinterval,
        @freq_subday_type       = @freqsubtype,
        @freq_subday_interval   = @freqsubinterval,
        @freq_relative_interval = @freqrelativeinterval,
        @freq_recurrence_factor = @freqrecurrencefactor,
        @active_start_date      = @activestartdate,
        @active_end_date        = @activeenddate,
        @active_start_time      = @activestarttimeofday,
        @active_end_time        = @activeendtimeofday

      IF (@retval <> 0)
      BEGIN
		GOTO UNDO
      END
    END

    -- And finally, add the job server
    EXECUTE @retval = msdb.dbo.sp_add_jobserver @job_id = @job_id, @server_name  = '(local)'

    IF (@retval <> 0)
    BEGIN
      GOTO UNDO
    END

  COMMIT TRANSACTION

  -- If this is an autostart LogReader or Distribution or Merge job, add the [new] '-Continuous' paramter to the command
  IF (@freqtype = 0x40) AND ((UPPER(@subsystem) = 'LOGREADER') OR (UPPER(@subsystem) = 'DISTRIBUTION') OR (UPPER(@subsystem) = 'MERGE'))
  BEGIN
	UPDATE msdb.dbo.sysjobsteps
	SET command = command + ' -Continuous'
	WHERE (job_id = @job_id)
	  AND ((@failure_detection = 0 and step_id = 1) or (@failure_detection = 1 and step_id = 2))
  END  

  -- If this is an autostart job, start it now (for backwards compatibility with 6.x SQLExecutive behaviour)
  IF (@freqtype = 0x40)
    EXECUTE msdb.dbo.sp_start_job @job_id = @job_id, @error_flag = 0

  RETURN(0)

UNDO:
	if @@TRANCOUNT = 1
		ROLLBACK TRAN
	else
		COMMIT TRAN
	return(1)

END
go

raiserror('Creating procedure sp_MScheck_subscription', 0,1)
go

CREATE PROCEDURE sp_MScheck_subscription (
@publication	sysname,  -- 	1 Tran, 2 Merge
@pub_type		int
)AS
declare @merge_pubid	uniqueidentifier
declare @tran_pubid		int

if @pub_type = 2
BEGIN
	if not exists (select * from sysobjects where name = 'sysmergepublications')
		begin
			raiserror(20054, 16, -1)
			return (1)
		end
	select @merge_pubid = pubid from sysmergepublications where name=@publication and publisher=@@SERVERNAME and publisher_db=db_name()
	if @merge_pubid is NULL
		begin
			raiserror(20026, 16, -1, @publication)
			return (1)
		end
	if EXISTS (select * from sysmergesubscriptions where pubid=@merge_pubid and subid<>pubid)
		select 1
	else 
		select 0
END
else	-- if not merge, it has to be tran level. For other level, a generic error will be returned
BEGIN
	if not exists (select * from sysobjects where name='syspublications')
		begin
			raiserror(20054, 16, -1)
			return (1)
		end
	select @tran_pubid = pubid from syspublications where name=@publication
	if @tran_pubid is NULL 
		begin
			raiserror(20026, 16, -1, @publication)
			return (1)
		end
	if EXISTS (select * from syssubscriptions where (srvid <> -1) and artid in 
           			(select artid from sysarticles where pubid=@tran_pubid))
      	select 1
    else
       	select 0
END
GO

exec dbo.sp_MS_marksystemobject sp_MScheck_subscription
go
grant execute on dbo.sp_MScheck_subscription to public
go


raiserror('Creating procedure sp_replicationoption', 0,1)
go

CREATE PROCEDURE sp_replicationoption (
@optname		sysname,
@value			nvarchar(5),
@security_mode	int = 0,
@login			sysname = 'sa',
@password		sysname = NULL,
@reserved       nvarchar(20) = NULL
)
AS
	DECLARE @optbit bit
    DECLARE @osql_cmd1 nvarchar (255)
    DECLARE @osql_cmd_full nvarchar (255)
	DECLARE @osql_for_nt int

	DECLARE @install_path nvarchar (255)

    DECLARE @retcode int
	DECLARE @undo_install nvarchar(20)
	DECLARE @no_scripts nvarchar(10)
    DECLARE @platform_nt binary
    
    SELECT @platform_nt = 0x1

    if	is_srvrolemember('sysadmin') <> 1
        BEGIN
            RAISERROR (15232, 14, -1)
            RETURN (1)
        END
	
	SELECT @no_scripts = 'no_scripts'

	SELECT @undo_install = 'undo_install'

	IF db_name() <> 'master'
	BEGIN
		RAISERROR(5001, 16,-1)
		GOTO FAILURE
	END

	IF LOWER(@optname) NOT IN ('transactional','merge')
	BEGIN
		RAISERROR(21014, 16, -1)
		GOTO FAILURE
	END
	IF LOWER(@value) NOT IN ('true','false')
	BEGIN
		RAISERROR(14137,16,-1)
		GOTO FAILURE
	END
	
	IF LOWER(@value) = 'true'
		SELECT @optbit = 1
	ELSE
		SELECT @optbit = 0

	/*
	** Check if the option is set as required already
	*/
	IF @reserved <> @undo_install AND EXISTS (SELECT * FROM MSreplication_options
		WHERE	optname  = @optname
		AND		value = @optbit)
	BEGIN
		IF LOWER(@value) = 'true'
			RAISERROR (21015, 10, -1, @optname)		
		ELSE
			RAISERROR (21016, 10, -1, @optname)
		GOTO FAILURE
	END

	/* Install replication */
	IF @optbit = 1
	BEGIN

		IF LOWER(@reserved) = @no_scripts
			GOTO NO_SCRIPTS

		-- Set the flag for platform
		IF (( platform() & @platform_nt = @platform_nt ))
			SELECT @osql_for_nt = 1
		ELSE
			SELECT @osql_for_nt = 0

		/* 
		** Get installation path
		*/
		EXECUTE @retcode = master.dbo.xp_regread 'HKEY_LOCAL_MACHINE',
				  'SOFTWARE\Microsoft\MSSQLServer\Setup',
				  'SQLPath',
				@param = @install_path OUTPUT
		IF @@ERROR<> 0 OR @retcode <> 0 or @install_path is NULL or @install_path=''
			BEGIN
				GOTO FAILURE       
			END

		/* 
		** Install replcom.sql and repltran.sql
		*/
		IF @security_mode = 1
			SELECT @osql_cmd1 = '"' + @install_path + '\binn\osql" -E ' 
		ELSE
			-- cannot specify -S w/ -E for local execution, SID does not map due to nofix bug
			SELECT @osql_cmd1 = '"' + @install_path + '\binn\osql" -U' + @login + ' -P' + 
				isnull(@password,'') + ' -S' + @@SERVERNAME + ' '

		select @osql_cmd1 = @osql_cmd1 + '-l30 -t30 '

		-- Install replcom.sql 
		-- bug24982 Only apply replcom.sql if it was not applied before.
		-- '-b' option will make osql stop at errors and return error code
		-- We must use this option.
		IF NOT EXISTS (SELECT * FROM MSreplication_options
			WHERE value = 1)
		BEGIN
			-- Initialize the Command
			IF (@osql_for_nt = 1)
				SELECT @osql_cmd_full = '" '
			ELSE
				SELECT @osql_cmd_full = ' '

			SELECT @osql_cmd_full = @osql_cmd_full +
				@osql_cmd1 + 
				' -dmaster' +  ' -b ' +
				' -i' + '"' + @install_path + '\install\replcom.sql"' + 
				' -o' + '"' + @install_path + '\install\replcom.out"' 

			IF (@osql_for_nt = 1)
				SELECT @osql_cmd_full = @osql_cmd_full + ' "'

			EXEC @retcode = master..xp_cmdshell @osql_cmd_full
			IF @@ERROR<> 0 OR @retcode <> 0
			BEGIN
				RAISERROR (14113, 16, -1, @osql_cmd_full, 'replcom.out')
				GOTO UNDO_INSTALL     
			END
		END

		IF LOWER(@optname) = 'transactional'
		BEGIN
			-- Install repltran.sql
			IF (@osql_for_nt = 1)
				SELECT @osql_cmd_full = '" '
			ELSE
				SELECT @osql_cmd_full = ' '

			SELECT @osql_cmd_full = @osql_cmd_full +
				@osql_cmd1 + 
				' -dmaster' +  ' -b ' +
				' -i' + '"' + @install_path + '\install\repltran.sql"' + 
				' -o' + '"' + @install_path + '\install\repltran.out"' 

			IF (@osql_for_nt = 1)
				SELECT @osql_cmd_full = @osql_cmd_full + ' "'

			EXEC @retcode = master..xp_cmdshell @osql_cmd_full
			IF @@ERROR<> 0 OR @retcode <> 0
			BEGIN
				RAISERROR (14113, 16, -1, @osql_cmd_full, 'repltran.out')
				GOTO UNDO_INSTALL     
			END

		END

		IF LOWER(@optname) = 'merge'
		BEGIN
			-- Install replmerg.sql 
			IF (@osql_for_nt = 1)
				SELECT @osql_cmd_full = '" '
			ELSE
				SELECT @osql_cmd_full = ' '

			SELECT @osql_cmd_full = @osql_cmd_full +
				@osql_cmd1 + 
				' -dmaster' + ' -b ' +
				' -i' + '"' + @install_path + '\install\replmerg.sql"' + 
				' -o' + '"' + @install_path + '\install\replmerg.out"' 
			
			IF (@osql_for_nt = 1)
				SELECT @osql_cmd_full = @osql_cmd_full + ' "'

			EXEC @retcode = master..xp_cmdshell @osql_cmd_full 
			
			IF  @@ERROR<> 0 OR @retcode <> 0
			BEGIN
				RAISERROR (14113, 16, -1, @osql_cmd_full, 'replmerg.out')
				GOTO UNDO_INSTALL     
			END
		END

NO_SCRIPTS:

		UPDATE MSreplication_options SET value = @optbit
			WHERE optname = @optname
		IF @@ERROR <> 0 
		BEGIN
			GOTO UNDO_INSTALL    
		END

	END
	/* Uninstall replication */
	ELSE
	BEGIN

		/* 
		** Make sure no distributor installed before dropping 
		** replication stored procedures
		*/
		IF EXISTS (SELECT * FROM master..sysservers
              WHERE  srvstatus & 8 <> 0)
		BEGIN
			RAISERROR (21021, 16, -1)
			RETURN(1)
		END

		UPDATE MSreplication_options SET value = @optbit
			WHERE optname = @optname
		IF @@ERROR <> 0 
		BEGIN
			GOTO FAILURE
		END

		/* 
		*********** Do not drop replication stored procs anymore.

		IF LOWER(@optname) = 'transactional'
		BEGIN
			if exists (select * from sysobjects
				where type = 'P '
						and name = 'sp_MSdrop_repltran')
			begin
				exec @retcode = dbo.sp_MSdrop_repltran
				if @@ERROR = 0 and @retcode = 0
					drop procedure sp_MSdrop_repltran
			end
		END

		IF LOWER(@optname) = 'merge'
		BEGIN
			if exists (select * from sysobjects
				where type = 'P '
						and name = 'sp_MSdrop_replmerg')
			begin
				exec @retcode = dbo.sp_MSdrop_replmerg
				if @@ERROR = 0 and @retcode = 0
					drop procedure sp_MSdrop_replmerg
			end
		END

		IF NOT EXISTS (SELECT * FROM MSreplication_options
			WHERE value = 1)
		BEGIN
			if exists (select * from sysobjects
				where type = 'P '
						and name = 'sp_MSdrop_replcom')
			begin
				exec @retcode = dbo.sp_MSdrop_replcom
				if @@ERROR = 0 and @retcode = 0
					drop procedure sp_MSdrop_replcom
			end
		END

		*/
	END

	RETURN(0)

UNDO_INSTALL:
	/* This is needed to drop the stored procedures that were created. */
	EXEC dbo.sp_replicationoption @optname =  @optname, 
		@value = 'false', @reserved = @undo_install

FAILURE:
	RETURN(1)
GO
exec dbo.sp_MS_marksystemobject sp_replicationoption
go
grant execute on dbo.sp_replicationoption to public
	

raiserror('Creating procedure sp_helpreplicationoption', 0,1)
go

CREATE PROCEDURE sp_helpreplicationoption (
@optname		sysname = NULL
)
AS
	DECLARE @optbit bit
	DECLARE @retcode int


	IF @optname IS NOT NULL AND LOWER(@optname) NOT IN ('transactional','merge')
	BEGIN
		RAISERROR(21014, 16, -1)
		GOTO FAILURE
	END
	
	SELECT optname, value, major_version, minor_version, revision 
		FROM MSreplication_options
		WHERE
			optname = @optname OR
			@optname = NULL

	RETURN(0)

FAILURE:
	RETURN(1)
GO
exec dbo.sp_MS_marksystemobject sp_helpreplicationoption
go
grant execute on dbo.sp_helpreplicationoption to public

raiserror('Creating procedure sp_MSgetreplnick', 0,1)
GO

create procedure sp_MSgetreplnick (
	@server		sysname = NULL,
	@db_name	sysname = NULL,
	@pubid		uniqueidentifier  = NULL,
	@nickname	int output
	)
as
	declare @srvid 			int
	
	if @db_name IS NULL
		select @db_name = db_name()

	/* Use 0 if the Server name is not passed in since it would be the local server */
	if @server IS NULL
		select @srvid = 0
	else			
		select @srvid = max(srvid) from master..sysservers where UPPER(srvname) = UPPER(@server)

	if (@pubid IS NOT NULL)
		begin
			select @nickname = max(replnickname) from MSmerge_replinfo 
				where repid in (select subid from sysmergesubscriptions
					where srvid = @srvid and db_name = @db_name and pubid = @pubid)
		end
	else
		begin
			select @nickname = max(replnickname) from MSmerge_replinfo 
				where repid in (select subid from sysmergesubscriptions
						where srvid = @srvid and db_name = @db_name)
		end
go

exec dbo.sp_MS_marksystemobject sp_MSgetreplnick
go
grant execute on dbo.sp_MSgetreplnick to public

raiserror('Creating procedure sp_MSreplcheck_publish', 0,1)
go

CREATE PROCEDURE sp_MSreplcheck_publish 
AS
    if	is_srvrolemember('sysadmin') <> 1  and
		is_member ('db_owner') <> 1
        BEGIN
            RAISERROR (21050, 14, -1)
            RETURN (1)
        END
GO


raiserror('Creating procedure sp_MSlocktable', 0,1)
go
CREATE PROCEDURE sp_MSlocktable
@ownername		sysname,
@tablename		sysname
AS
	declare @ispublisher			bit
	declare @retcode			int
	declare @procname			sysname
	declare @objid 				int
	declare @qualified_name		nvarchar(255)
	select @qualified_name = QUOTENAME(@ownername) + '.' + QUOTENAME(@tablename)
	select @objid = object_id(@qualified_name)
	if @objid is NULL
		begin
			select @ispublisher = 0
			select @qualified_name = QUOTENAME(@tablename)
			select @objid = object_id(@qualified_name)
		end
	else
		select @ispublisher = 1
	
	exec dbo.sp_MSreplcheck_connection @objid = @objid 
	
	select @procname = select_proc from sysmergearticles where objid = @objid and select_proc is not NULL
	exec @retcode = @procname @type = 7

--  exec ('select count(*) from ' + @ownername + '.' + @tablename + ' (tablock holdlock) where 1 = 2')
go
exec dbo.sp_MS_marksystemobject sp_MSlocktable
go
grant execute on dbo.sp_MSlocktable to public
go

raiserror('Creating procedure sp_MSenumcolumns', 0,1)
go
CREATE PROCEDURE sp_MSenumcolumns
	@pubid uniqueidentifier,
	@artid uniqueidentifier
AS
	declare @retcode			int
	declare @procname			sysname

	select @procname = select_proc from sysmergearticles where pubid = @pubid and artid = @artid
	exec @retcode = @procname @type =6

go
exec dbo.sp_MS_marksystemobject sp_MSenumcolumns
go
grant execute on dbo.sp_MSenumcolumns to public
go

/*
** Get pubid through connection_ID and check permission of this publication
*/

raiserror('Creating procedure sp_MSsetaccesslist', 0,1)
go
CREATE PROCEDURE sp_MSsetaccesslist
@publication 	sysname,
@publisher 		sysname,
@publisher_db	sysname
AS
declare @pubid uniqueidentifier
		select @pubid = pubid from sysmergepublications where 
					name = @publication and UPPER(publisher)=UPPER(@publisher) and publisher_db=@publisher_db
		exec dbo.sp_MSreplcheck_connection
			@publication = @publication,
			@pubid = @pubid,
			@is_init = 1
go
exec dbo.sp_MS_marksystemobject sp_MSsetaccesslist
go
grant execute on dbo.sp_MSsetaccesslist to public
go
			
raiserror('Creating procedure sp_MSreplcheck_connection', 0,1)
go

CREATE PROCEDURE sp_MSreplcheck_connection
@publication sysname = NULL,
@artid uniqueidentifier = NULL,
@repid uniqueidentifier = NULL,
@pubid uniqueidentifier = NULL,
@objid int				= NULL,
@tablenick int = NULL,
@is_init bit = 0
AS
	-- sysadmin or db_owner have access
	if is_srvrolemember('sysadmin') = 1 or 
		is_member('db_owner') = 1
		return 0

	declare @retcode int
	declare @cached_id uniqueidentifier

	-- Need login_time to uniquely identify a connection.
	declare @login_time datetime
	select @login_time = login_time from master..sysprocesses where spid = @@spid

	select @cached_id = pubid from tempdb.dbo.MSpublisher_access where 
		spid = @@spid and
		login_time = @login_time

	-- If spid with publication in the cache, return success.
	if @cached_id is null
	begin
		-- This stored procedure might be called by common sprocs at
		-- both the publisher and the subscriber by the merge agent
		-- The merge agent will call this sp with @is_init = 1 before
		-- any other calls to the publisher. All the other calls will
		-- set @is_init to 0.
		if @is_init = 0
		begin
			RAISERROR (14126, 11, -1)
			return (1)
		end
		else
		begin
			exec @retcode = dbo.sp_MSreplcheck_pull @publication = @publication,
				@pubid = @pubid
			if @retcode <> 0 or @@error <> 0
				return (1)
		end
	end
	else
	begin
		if @pubid is not null
		begin
			if @pubid <> @cached_id
			begin
				RAISERROR (14126, 11, -1)
				return (1)
			end

		end
		else if @tablenick is not null
		begin
			if not exists (select * from sysmergearticles where pubid = @cached_id and 
				nickname = @tablenick)
			begin
				RAISERROR (14126, 11, -1)
				return (1)
			end
		end
		else if @artid is not null
		begin
			if not exists (select * from sysmergearticles where pubid = @cached_id and 
				artid = @artid)
			begin
				RAISERROR (14126, 11, -1)
				return (1)
			end
		end
		else if @objid is not null
		begin
			if not exists (select * from sysmergearticles where pubid = @cached_id and 
				objid=@objid)
			begin
				RAISERROR (14126, 11, -1)
				return (1)
			end
		end
		
		else if @publication is not null
		begin
			if not exists (select * from sysmergepublications where pubid = @cached_id and 
				name = @publication)
			begin
				RAISERROR (14126, 11, -1)
				return (1)
			end
		end
		else if @repid is not null
		begin
			if not exists (select * from sysmergesubscriptions where pubid = @cached_id and 
				subid = @repid)
			begin
				RAISERROR (14126, 11, -1)
				return (1)
			end
		end
	end
GO
exec dbo.sp_MS_marksystemobject sp_MSreplcheck_connection
go
grant execute on dbo.sp_MSreplcheck_connection to public
go

raiserror('Creating procedure sp_MSreplcheck_pull', 0,1)
go

CREATE PROCEDURE sp_MSreplcheck_pull (
@publication sysname,
@raise_fatal_error bit = 1,
@pubid uniqueidentifier = NULL
)
AS
	-- sysadmin or db_owner have access
	if is_srvrolemember('sysadmin') = 1 or 
		is_member('db_owner') = 1
		return 0

	-- Need login_time to uniquely identify a connection.
	declare @login_time datetime
	select @login_time = login_time from master..sysprocesses where spid = @@spid

	-- If spid with publication in the cache, return success.
	if exists (select * from tempdb.dbo.MSpublisher_access where 
		spid = @@spid and
		login_time = @login_time and
		db_id = db_id() and
		publication = @publication)
		return (0)

	declare @has_access bit
    DECLARE @distribdb sysname
    DECLARE @distproc nvarchar (255)
    DECLARE @retcode int
	DECLARE @dist_rpcname sysname
	DECLARE @database sysname
	declare @login sysname

	select @login = suser_sname(suser_sid())
	select @database = db_name()

    EXEC @retcode = dbo.sp_helpdistributor 	@rpcsrvname = @dist_rpcname OUTPUT,
                                       	@distribdb   = @distribdb   OUTPUT
    IF @retcode <> 0 or @@error <> 0
    BEGIN
         RAISERROR (14071, 16, -1)
         return (1)
    END

    IF @retcode <> 0 OR @distribdb IS NULL OR @dist_rpcname IS NULL
    BEGIN
        RAISERROR (14071, 16, -1)
        return(1)
    END

    SELECT @distproc = RTRIM(@dist_rpcname) + '.' + RTRIM(@distribdb) + '.dbo.sp_MSpublication_access'
    EXEC @retcode = @distproc
         @publisher = @@SERVERNAME,
		 @publisher_db = @database,
		 @publication = @publication,
		 @operation = 'check',
		 @login = @login,
		 @has_access = @has_access output

    IF @@error <> 0 OR @retcode <> 0
    BEGIN
        RAISERROR (14042, 16, -1)
        return (1)
    END

	if @has_access = 0
	begin

		-- We don't have access if we reach here, return error
		IF @raise_fatal_error = 1
			RAISERROR (21049, 14, -1, @login, @publication)
		ELSE
			RAISERROR (21049, 10, -1, @login, @publication)
		return(1)
	end

ADD_CACHE:

	-- If we are here, we know that the connection has access and is not in the cache
	-- add it in to the cache.
		
	-- Clear the cache to keep it small.
	exec @retcode = dbo.sp_MSflush_access_cache
	if @retcode <> 0 or @@error <> 0
		return (1)
			
	insert tempdb.dbo.MSpublisher_access
		(spid, db_id, publication, login_time, pubid) values
		(@@spid, db_id(), @publication, @login_time, @pubid)

	if @@error <> 0
		return (1)

	return (0)
GO

raiserror('Creating procedure sp_MSreplcheck_qv', 0, 1)
GO

create procedure sp_MSreplcheck_qv
as
begin

	set nocount on 
		
	declare @qv_replication varchar(10)
	declare @qv_engine varchar(10)
	declare @qv_value_replication integer
	declare @qv_value_engine integer

	select @qv_replication = '2745196162', @qv_engine = '845129433'

	exec @qv_value_replication = master.dbo.xp_qv @qv_replication 	
	if @@ERROR <> 0 
		select @qv_value_replication = 1

	exec @qv_value_engine = master.dbo.xp_qv @qv_engine
	if @@ERROR <> 0
		select @qv_value_engine = 1

	-- magic number 1 assumes least common setting on all failure states
	select isnull( @qv_value_replication, 1 ) as VALUE_REPLICATION, isnull( @qv_value_engine, 1 ) as VALUE_ENGINE


end
go

exec dbo.sp_MS_marksystemobject sp_MSreplcheck_qv
go	

grant execute on dbo.sp_MSreplcheck_qv to public
go

raiserror('Creating procedure sp_reinitmergepullsubscription', 0, 1)
GO

create procedure sp_reinitmergepullsubscription
	@publisher		sysname  = 'all',
	@publisher_db	sysname  = 'all',
	@publication	sysname  = 'all'
AS
	declare @schemaversion			int
	declare @schematype				smallint
	declare @schemaguid				uniqueidentifier
    declare @pubid					uniqueidentifier
    declare @subid					uniqueidentifier
    declare @artid					uniqueidentifier
	/*
	** Replace 'all' with '%'
	*/

	if LOWER(@publication) = 'all'
		SELECT @publication = '%'

	if LOWER(@publisher) = 'all'
		SELECT @publisher = '%'

	if LOWER(@publisher_db) = 'all'
		SELECT @publisher_db = '%'
	/*
	** At subscriber side, we need to qualify the publication with server name and database name
	*/
    IF NOT EXISTS (SELECT * FROM sysmergepublications WHERE name LIKE @publication 
    	and ((@publisher = N'%') or (UPPER(publisher) = UPPER(@publisher))) 
    	and publisher_db like @publisher_db)
    	
        BEGIN
        IF @publication = '%'
                RAISERROR (14008, 11, -1)
        ELSE
                RAISERROR (20026, 11, -1, @publication)
        RETURN (1)
        END
	
	Declare SYN_CUR CURSOR LOCAL FAST_FORWARD FOR 
		select subs.subid 
			from sysmergepublications pubs, sysmergesubscriptions subs
				where pubs.name LIKE  @publication
					AND ((@publisher = N'%') OR (UPPER(pubs.publisher) = UPPER(@publisher)))
					AND pubs.publisher_db LIKE @publisher_db
					AND pubs.pubid=subs.pubid
					AND subs.pubid<>subs.subid
	FOR READ ONLY
	open SYN_CUR
	fetch SYN_CUR into @subid
	while (@@fetch_status<>-1)
	BEGIN	
		update MSmerge_replinfo set schemaversion=-1, recgen = NULL, recguid=NULL, sentgen=NULL, sentguid = NULL where repid=@subid  -- use -1 to replace 0
		fetch next from SYN_CUR into @subid								 -- so that it won't be treated as a new susbscription	
	END
	close SYN_CUR
	deallocate SYN_CUR
	-- Forget that publisher ever sent us any generations.  They must be resent.
	-- Publication cleanup will remove the genhistory rows.

	if @publication = '%'
		-- get them all
		update MSmerge_replinfo set recgen = NULL, recguid=NULL, sentgen=NULL, sentguid = NULL
	else
		begin
		select @pubid = pubid from sysmergepublications where name = @publication
		update MSmerge_replinfo set recgen = NULL, recguid=NULL, sentgen=NULL, sentguid = NULL
			where repid in (select subid from sysmergesubscriptions where pubid = @pubid)
		end
GO

exec dbo.sp_MS_marksystemobject sp_reinitmergepullsubscription
go	
grant execute on dbo.sp_reinitmergepullsubscription to public

raiserror('Creating procedure sp_MSreplcheck_subscribe', 0,1)
go

CREATE PROCEDURE sp_MSreplcheck_subscribe
AS
	/*
    ** Only the System Administratr (SA) or the Database Owner (dbo) 
    ** can subscribe from the subscribing database.
	*/
    if  is_srvrolemember('sysadmin') <> 1 and is_member ('db_owner') <> 1 
        BEGIN
            RAISERROR (21050, 14, -1)
            RETURN (1)
        END
GO

raiserror('Creating procedure sp_MSreplicationcompatlevel', 0,1)
GO
create procedure sp_MSreplicationcompatlevel
@dbname 			sysname,
@cmptlevel			float(8)
As
	declare		@is_distdb	smallint

	select @is_distdb = 0

	IF EXISTS (select * from msdb..sysobjects where name='MSdistributiondbs')
		begin
			IF EXISTS (SELECT * FROM msdb..MSdistributiondbs where name=@dbname)
				select @is_distdb = 1
		end
		
	/*
	** Parameter check
	** @dbname
	*/
	IF NOT EXISTS (SELECT * FROM master.dbo.sysdatabases WHERE
		name = @dbname)
	BEGIN
		RAISERROR(15010, 16, -1, @dbname)
		RETURN(2)
	END

	/*
	** Parameter check. NOTE
	** @cmptlevel
	*/
	IF @cmptlevel<6.0
	BEGIN
    	RAISERROR(20060,16,-1)
		RETURN(2)
	END

	/*
	** If cmptlevel is lower than 7.0, special attention should be paid. 
	** If current database is a distribution database or is involed in merge
	** replication, then it can not be set to a level lower than 7.0.
	*/
	
	create table #tmp (any_merge smallint NOT NULL)
	insert into #tmp exec ('select count(*) from ' + @dbname + '..sysobjects where name=' + '''sysmergesubscriptions''' )
	if (exists(select any_merge from #tmp where any_merge>0) OR @is_distdb = 1) 
				AND (@cmptlevel<7.0) 
		begin
			drop table #tmp
			return 1
		end
	else 
		begin
			drop table #tmp
			return 0
		end
go

exec dbo.sp_MS_marksystemobject sp_MSreplicationcompatlevel
go

raiserror('Creating procedure sp_MSgenreplnickname', 0,1)
GO

create procedure sp_MSgenreplnickname
			@srcguid	uniqueidentifier,	/* Source Guid */
			@repnick	int	output	/* nickname */
	as
	declare @binguid binary(16)
	declare	@nickname		int
	set @binguid = convert(binary(16), @srcguid)
	select @nickname = convert(int, convert(binary(4),substring( convert(nchar(8),@binguid), 1, 2)))
	while exists (select replnickname from MSmerge_replinfo where replnickname = @nickname)
		select @nickname = @nickname + 1
	select @repnick = @nickname
go

exec dbo.sp_MS_marksystemobject sp_MSgenreplnickname
go
grant execute on dbo.sp_MSgenreplnickname to public

raiserror('Creating procedure sp_MSmergesubscribedb', 0,1)
GO

CREATE PROCEDURE sp_MSmergesubscribedb(
	@value sysname
	) AS

    SET NOCOUNT ON

    /*
    ** Declarations.
    */
	declare @retcode 				int
	

    /*
    ** Security Check
    */

	EXEC @retcode = dbo.sp_MSreplcheck_subscribe
	IF @@ERROR <> 0 or @retcode <> 0
		RETURN(1)


	/*
	** Initialization
	*/


	/*
	** Parameter check
	** @value
	*/
	IF LOWER(@value) NOT IN ('true','false')
	BEGIN
      RAISERROR(14137,16,-1)
	  RETURN(1)
	END

	IF LOWER(@value) = 'true'
		BEGIN		
			execute @retcode = dbo.sp_MScreate_mergesystables
			if @@ERROR <> 0 or @retcode <> 0
				begin
					return (1)
				end
		END
	
	-- We assume we will do nothing about disabling a subscriber
	
GO

exec dbo.sp_MS_marksystemobject sp_MSmergesubscribedb
go

grant execute on dbo.sp_MSmergesubscribedb to public
go 

raiserror('Creating procedure sp_MSenumallpublications', 0,1)
go

CREATE PROCEDURE sp_MSenumallpublications(
@publisherdb sysname = '%', 
@replication_type tinyint = 1,
@agent_login sysname = NULL,
@security_check bit = 1 -- Security check by default so that things depending on security 
                        -- filtering will not break immediately
)

as
	set nocount on
	declare @dbname 		sysname
	declare @trans 			tinyint
	declare @merge 			tinyint
	declare @3rdparty		tinyint
	declare @retcode		int
	DECLARE @dist_rpcname	sysname
	declare @distribdb		sysname
	declare @login			sysname
	declare @proc			nvarchar(255)
	declare @distbit		int
	declare @is_user_admin	bit
	declare @same_as_user	bit

	-- UI: If the distributor is not installed, return empty result
    if not exists (SELECT * FROM master..sysservers
              WHERE  srvstatus & 8 <> 0)
		return (0)

	/* Initializations */
	select @trans = 1 
	select @merge = 2
	select @3rdparty = 0
	select @login = suser_sname(suser_sid())
    SELECT @distbit = 16
	select @is_user_admin = 0
	select @same_as_user = 0

	-- Get publication list
	create table #pubdbs (publisher_db sysname NOT NULL, replication_type int NOT NULL)

	/* Return everything if @replication_type is not in (@3rdparty, @trans, @merge) */
	if not @replication_type in (@3rdparty, @trans, @merge)
		select @replication_type = null

	if @replication_type = @trans or @replication_type is null
		insert into #pubdbs select name, @trans from master..sysdatabases where 
			name like @publisherdb and category & 1 <> 0 and 
			(isnull(databaseproperty(name, N'issuspect'), 0) = 0 and isnull(databaseproperty(name, N'isshutdown'), 0) = 0) and 
			has_dbaccess(name) = 1
	if @replication_type = @merge or @replication_type is null
		insert into #pubdbs select name, @merge from master..sysdatabases where 
			name like @publisherdb and category & 4 <> 0 and 
			(isnull(databaseproperty(name, N'issuspect'), 0) = 0 and isnull(databaseproperty(name, N'isshutdown'), 0) = 0) and 
			has_dbaccess(name) = 1
	if @replication_type = @3rdparty
		insert into #pubdbs select name, @3rdparty from master..sysdatabases where 
			name like @publisherdb and category & @distbit <> 0 and 
			(isnull(databaseproperty(name, N'issuspect'), 0) = 0 and isnull(databaseproperty(name, N'isshutdown'), 0) = 0) and 
			has_dbaccess(name) = 1

	create table #MSenumpublications 
			(publisher_db sysname NOT NULL, publication sysname NOT NULL, replication_type tinyint NOT NULL, 
			immediate_sync bit NOT NULL, allow_pull bit NOT NULL, allow_anonymous bit NOT NULL, 
			enabled_for_internet bit NOT NULL, repl_freq tinyint NOT NULL, immediate_sync_ready bit NOT NULL, 
			allow_sync_tran bit NOT NULL, independent_agent bit NOT NULL, is_db_owner int NOT NULL, 
			thirdparty_flag bit NOT NULL, vendor_name sysname NULL, publisher sysname NULL, description nvarchar(255) NULL, distribution_db sysname NULL)

	declare hCForEachDb CURSOR LOCAL FAST_FORWARD FOR select publisher_db, replication_type from  #pubdbs
	FOR READ ONLY
	open hCForEachDb
	fetch hCForEachDb into @dbname, @replication_type
	/* Loop for each database */
	while (@@fetch_status >= 0) 
	begin
		if (@replication_type) = @trans
			select @proc = quotename(@dbname) + '.dbo.sp_MSenumtranpublications'
		else if (@replication_type) = @merge
			select @proc = quotename(@dbname) + '.dbo.sp_MSenummergepublications'
		else if (@replication_type) = @3rdparty
			select @proc = quotename(@dbname) + '.dbo.sp_MSenum3rdpartypublications'
		insert into #MSenumpublications exec @retcode = @proc
		if @@ERROR <> 0 or @retcode <> 0
			return (1)
		fetch hCForEachDb into @dbname, @replication_type
	end /* while FETCH_SUCCESS */

	-- Prepare for filtering.
	create table #admin_publications (publisher_db sysname not null, 
		publication sysname not null)

	create table #agent_publications (publisher_db sysname not null,
		publication sysname not null)


    IF (@security_check <> 0)
    BEGIN
	
        EXEC @retcode = dbo.sp_helpdistributor 	@rpcsrvname = @dist_rpcname OUTPUT,
                                           	@distribdb   = @distribdb   OUTPUT

        IF @@error <> 0 OR @retcode <> 0
	    	RETURN (1)

        IF @distribdb is null
        BEGIN
            RAISERROR (14071, 16, -1)
            RETURN (1)
        END

        SELECT @proc = RTRIM(@dist_rpcname) + '.' + RTRIM(@distribdb) + '.dbo.sp_MSpublication_access'

		-- Optimization
		if is_srvrolemember('sysadmin') = 1
			select @is_user_admin = 1
		else
			insert into #admin_publications EXEC @retcode = @proc
				 @publisher = @@SERVERNAME,
				 @operation = 'get_publications',
				 @login = @login


		if suser_sid(@agent_login) = suser_sid()
			select @same_as_user = 1
		else
			insert into #agent_publications EXEC @retcode = @proc
				@publisher = @@SERVERNAME,
				@operation = 'get_publications',
				@login = @agent_login
		
    END -- IF (@security_check <> 0) 

	-- workaround of a server bug of leaving tran open when
	-- insert into exec failed.
	while(@@trancount <> 0) commit tran

DONE2:

	select pub.publisher_db, pub.publication, pub.replication_type, 
			pub.immediate_sync, pub.allow_pull, pub.allow_anonymous, 
			pub.enabled_for_internet, pub.repl_freq, pub.immediate_sync_ready, 
			pub.allow_sync_tran, pub.independent_agent, N'agent_access' = case 
				when 
					(@same_as_user = 1 or
					exists (select * from #agent_publications agent where
					agent.publisher_db = pub.publisher_db and
					agent.publication = pub.publication))
					then convert(bit,1)
				else convert(bit,0)
				end,
			pub.thirdparty_flag,
			pub.vendor_name, pub.publisher, pub.description, pub.distribution_db
	 from #MSenumpublications pub where exists (select * from #admin_publications admin where
		pub.publisher_db = admin.publisher_db and
		pub.publication = admin.publication) or
        @security_check = 0 or
		pub.is_db_owner = 1 or
		@is_user_admin = 1
	 order by pub.publication, pub.publisher_db

	return (0)
go

grant execute on dbo.sp_MSenumallpublications to public
go 

raiserror('Creating procedure sp_MSenumtranpublications', 0,1)
go

CREATE PROCEDURE sp_MSenumtranpublications
as
	set nocount on
	select db_name(), name, 1, immediate_sync, allow_pull, allow_anonymous, 
		enabled_for_internet, repl_freq, immediate_sync_ready, 
		allow_sync_tran, independent_agent, is_member('db_owner'),
		0, -- thirdparty
		'Microsoft SQL Server', @@servername, description,
		convert(sysname, null)
		from syspublications pubs
		where exists (select * from sysarticles art where pubs.pubid = art.pubid) 
			and status <> 0
go


raiserror('Creating procedure sp_MSenummergepublications', 0,1)
go

CREATE PROCEDURE sp_MSenummergepublications

as
	set nocount on
	select db_name(), name, 2, 1, allow_pull, allow_anonymous, enabled_for_internet, 0, snapshot_ready, 0, 1, is_member('db_owner'),
		0, --thirdparty
		'Microsoft SQL Server', publisher, description,
		convert(sysname, null)
		from 
		sysmergepublications where status <> 0
go

raiserror('Creating procedure sp_MSenum3rdpartypublications', 0,1)
go

CREATE PROCEDURE sp_MSenum3rdpartypublications
as
	set nocount on
	select pubs.publisher_db, publication, 
		case when publication_type <> 2 then 1
		else 2
		end,  --replication_type, 1 tran, 2 merge ; pub type 0 tran 1 snapshot, 2 merge
		immediate_sync, allow_pull, allow_anonymous, 
		0,	--enabled_for_internet,
		case when publication_type = 0 then 0
		else 1
		end,  --repl_freq, 
		1,	--immediate_sync_ready, always return 1 so that UI will not warn
		0,	-- allow_sync_tran, 
		independent_agent, 
		is_member('db_owner'),
		1, --thirdparty
		pubs.vendor_name,
		srv.srvname,
		pubs.description,
		db_name()

		from MSpublications pubs, master..sysservers srv
		where exists (select * from MSarticles art where 
				pubs.publication_id = art.publication_id)  and
			thirdparty_flag <> 0 and
			publisher_id = srvid
go


dump tran master with no_log
GO

raiserror('Creating procedure sp_reinitpullsubscription', 0,1)
go

CREATE PROCEDURE sp_reinitpullsubscription (
    @publisher sysname,
    @publisher_db sysname,
    @publication sysname = 'all'   					/* publication name */
    )AS

	SET NOCOUNT ON
    
	declare @subscription_type int	
	declare @sync_type tinyint
	/*
    ** Security Check
    */
	
  	declare @retcode 	int  
	EXEC @retcode = dbo.sp_MSreplcheck_subscribe
	IF @@ERROR <> 0 or @retcode <> 0
		RETURN(1)

    /*
    ** Initializations.
    */
   
    /*
    ** Parameter Check: @publisher
    ** Check to make sure that the publisher is define
    */
    IF @publisher IS NULL
    BEGIN
        RAISERROR (14043, 16, -1, '@publisher')
        RETURN (1)
    END

    IF @publisher = 'all'
    BEGIN
        RAISERROR (14136, 16, -1)
        RETURN (1)
    END

    EXECUTE @retcode = dbo.sp_validname @publisher

    IF @@ERROR <> 0 OR @retcode <> 0
       RETURN (1)
    

    /*
    ** Parameter Check: @publisher_db
    */

    IF @publisher_db IS NULL
    BEGIN
        RAISERROR (14043, 16, -1, '@publisher_db')
        RETURN (1)
    END

    IF @publisher_db = 'all'
    BEGIN
        RAISERROR (14136, 16, -1)
        RETURN (1)
    END

    EXECUTE @retcode = dbo.sp_validname @publisher_db

    IF @@ERROR <> 0 OR @retcode <> 0
       RETURN (1)

    /*
    ** Parameter Check: @publication
	** 
    */
    IF @publication IS NULL
    BEGIN
        RAISERROR (14043, 16, -1, '@publication')
        RETURN (1)
    END

    IF LOWER(@publication) = 'all'
		select @publication = '%'
	ELSE
	BEGIN
		EXECUTE @retcode = dbo.sp_validname @publication

		IF @@ERROR <> 0 OR @retcode <> 0
		RETURN (1)
	END
		
    IF NOT EXISTS (SELECT * FROM  MSreplication_subscriptions 
                WHERE UPPER(publisher) = UPPER(@publisher) AND
                      publisher_db  = @publisher_db AND
					  publication like @publication )
	BEGIN
			RAISERROR(14135, 11, -1,  @publisher, @publisher_db, @publication)
			RETURN(1)
	END
		
	select @sync_type = immediate_sync 
		from MSreplication_subscriptions
    	WHERE UPPER(publisher) = UPPER(@publisher) AND publisher_db  = @publisher_db AND publication like @publication 

	IF @sync_type = 0
	BEGIN
		raiserror(21059, 16, -1)
		return (1)
	END
		
	UPDATE MSreplication_subscriptions set 
		transaction_timestamp = 0x00,
		subid = NULL 
		WHERE UPPER(publisher) = UPPER(@publisher) AND
                      publisher_db  = @publisher_db AND
					  publication like @publication 
	if @@ERROR<>0 
		RETURN (1)
GO

grant execute on dbo.sp_reinitpullsubscription to public
go
    
raiserror('Creating procedure sp_addpullsubscription', 0,1)
go

CREATE PROCEDURE sp_addpullsubscription (
    @publisher sysname,
    @publisher_db sysname,
    @publication sysname,    /* publication name */
	@independent_agent nvarchar(5) = 'true',  /* true or false */
    @subscription_type nvarchar(9) = 'anonymous',     /* subscription_type, pull or anonymous */
	@description nvarchar(100) = NULL,
	-- SyncTran
    @update_mode          nvarchar(15) = 'read only', -- Can be 'read only', 'sync tran'
    @immediate_sync		bit = 1
	 ) AS

    SET NOCOUNT ON

    /*
    ** Declarations.
    */

    DECLARE @retcode int
    DECLARE @subscription_type_id int   /* 1 = pull, 2 = anonymous */
	DECLARE @independent_agent_id bit
	-- SyncTran
	DECLARE @update_mode_id     tinyint 


	/* 
	** Check if replication components are installed on this server
	*/
	exec @retcode = dbo.sp_MS_replication_installed
	if (@retcode <> 1)
	begin
		return (1)
	end
    
	/*
    ** Security Check
    */

	EXEC @retcode = dbo.sp_MSreplcheck_subscribe
	IF @@ERROR <> 0 or @retcode <> 0
		RETURN(1)

    /*
    ** Initializations.
    */

    /*
    ** Parameter Check: @publisher
    ** Check to make sure that the publisher is define
    */
    IF @publisher IS NULL
    BEGIN
        RAISERROR (14043, 16, -1, '@publisher')
        RETURN (1)
    END

    IF @publisher = 'all'
    BEGIN
        RAISERROR (14136, 16, -1)
        RETURN (1)
    END

    EXECUTE @retcode = dbo.sp_validname @publisher

    IF @@ERROR <> 0 OR @retcode <> 0
       RETURN (1)
    

    /*
    ** Parameter Check: @publisher_db
    */

    IF @publisher_db IS NULL
    BEGIN
        RAISERROR (14043, 16, -1, '@publisher_db')
        RETURN (1)
    END

    IF @publisher_db = 'all'
    BEGIN
        RAISERROR (14136, 16, -1)
        RETURN (1)
    END

    EXECUTE @retcode = dbo.sp_validname @publisher_db

    IF @@ERROR <> 0 OR @retcode <> 0
       RETURN (1)

    /*
    ** Parameter Check: @publication
	** 
    */
    IF @publication IS NULL
    BEGIN
        RAISERROR (14043, 16, -1, '@publication')
        RETURN (1)
    END

    IF @publication = 'all'
    BEGIN
        RAISERROR (14136, 16, -1)
        RETURN (1)
    END

    EXECUTE @retcode = dbo.sp_validname @publication

    IF @@ERROR <> 0 OR @retcode <> 0
       RETURN (1)

    IF @independent_agent IS NULL OR LOWER(@independent_agent) NOT IN ('true', 'false')
        BEGIN
            RAISERROR (14148, 16, -1, '@independent_agent')
            RETURN (1)
        END

    IF LOWER(@independent_agent) = 'true' SELECT @independent_agent_id = 1
    ELSE SELECT @independent_agent_id = 0
    /*
    ** Parameter Check:  @subscription_type
    ** The @status value can be:
    **
    **      type_id            type
    **      ======            ========
	**			 0			  push
    **           1            pull
    **           2            anonymous
	**
	**	Note: @subscription_type = push is only used by distribution agents
    */
	
    IF @subscription_type IS NULL OR LOWER(@subscription_type) NOT IN ('push', 'pull','anonymous')
    BEGIN
        RAISERROR (20016, 16, -1)
        RETURN (1)
    END


    IF LOWER(@subscription_type) = 'pull'    
		SELECT @subscription_type_id = 1
    ELSE IF LOWER(@subscription_type) = 'anonymous'  
		SELECT @subscription_type_id = 2
	ELSE
		SELECT @subscription_type_id = 0

	IF @independent_agent_id = 0 AND @subscription_type_id = 2
	BEGIN
		RAISERROR (21026, 16, -1)
		RETURN (1)
	END

	-- SyncTran
    /*
	**  Parameter check: @update_mode
	*/
    IF @update_mode IS NULL OR LOWER(@update_mode) NOT IN ('read only', 'sync tran')
    BEGIN
	    RAISERROR (20502, 16, -1, '@update_mode')
        RETURN (1)
    END

    IF LOWER(@update_mode) = 'sync tran' 
    	begin
       		SELECT @update_mode_id = 1
       		if @subscription_type_id = 2  -- Anonymous subscriptions should not be allowed to 
       			begin					  -- subscribe with 'synctran option'	
       				RAISERROR (21057, 16, -1)
					RETURN (1)
				end
		end	
    ELSE 
        SELECT @update_mode_id = 0
    -- SyncTran

	begin tran
    save TRAN addpullsubscription
	
    /* 
	** Check to see if MSreplication_subscriptions and MSsubscription_properties 
	** tables exists.
	** If not, create it.
	*/
	exec @retcode = dbo.sp_MScreate_sub_tables
		@tran_sub_table = 1,
		@property_table = 1
	IF @@ERROR <> 0 or @retcode <> 0
		goto UNDO
	
	/*
    ** Check to make sure that the subscription does not already exist
    */
	-- Delete the push subscription entry first. If may be obsolete and left by 
	-- defunct push agents
	delete MSreplication_subscriptions 
                WHERE UPPER(publisher) = UPPER(@publisher) AND
                      publisher_db  = @publisher_db AND
					  publication = @publication and
					  subscription_type = 0
	if @@error <> 0
		goto UNDO

	-- It is not allowed to subscribe to the same publication twice even with
	-- differnet publication type. 
    IF EXISTS (SELECT * FROM  MSreplication_subscriptions 
                WHERE UPPER(publisher) = UPPER(@publisher) AND
                      publisher_db  = @publisher_db AND
					  publication = @publication)
					  /*
						 OR
					  -- If the subscription is already added by the distribution agent
					  (@independent_agent_id = 0 AND 
					  (publication IS NULL OR
					  publication = ''))) AND
					  independent_agent = @independent_agent_id AND
					  subscription_type = @subscription_type_id) */
    BEGIN
        RAISERROR (14058, 16, -1)
        GOTO UNDO
    END

  
    /*
    ** Add the subscription
    */

    INSERT MSreplication_subscriptions  (publisher,
                                    publisher_db,
                                    publication,
									independent_agent,
                                    subscription_type,
                                    distribution_agent,
									description,
									time,
									transaction_timestamp,
									-- SyncTran
									update_mode,
									immediate_sync)
       VALUES (@publisher,
                   @publisher_db,
                   @publication,
				   @independent_agent_id,    
                   @subscription_type_id,
                   NULL,
				   @description,
				   getdate(),
				   0,
				   -- SyncTran
				   @update_mode_id,
				   @immediate_sync
				   )
    IF @@ERROR <> 0
    BEGIN
       RAISERROR (14057, 16, -1)
       GOTO UNDO
    END

    COMMIT TRAN

	RETURN (0)

UNDO:
    IF @@TRANCOUNT > 0
	begin
        ROLLBACK TRAN addpullsubscription
        COMMIT TRAN   
	end
	return 1
go
 

raiserror('Creating procedure sp_addpullsubscription_agent', 0,1)
go

CREATE PROCEDURE sp_addpullsubscription_agent (
    @publisher sysname,
    @publisher_db sysname,
    @publication sysname,         /* publication name */
	@subscriber sysname	= NULL,
    @subscriber_db sysname = NULL,
	@subscriber_security_mode		int = NULL,						/* 0 standard; 1 integrated */
	@subscriber_login				sysname = NULL,
	@subscriber_password			sysname = NULL,
	@distributor sysname = @publisher,
	@distribution_db sysname = NULL,
	@distributor_security_mode int = 0,
	@distributor_login sysname = 'sa',
	@distributor_password sysname = NULL,
	@optional_command_line nvarchar(4000) = '',
    @frequency_type  int = 2 ,  /* 2== OnDemand */
    @frequency_interval int = 1, 
    @frequency_relative_interval int = 1, 
    @frequency_recurrence_factor int = 1, 
	@frequency_subday int = 1, 
    @frequency_subday_interval int = 1 ,
    @active_start_time_of_day int = 0, 
    @active_end_time_of_day int = 0,         
    @active_start_date int = 0, 
    @active_end_date int =0,
    @distribution_jobid	binary(16) = NULL OUTPUT,
	@encrypted_distributor_password bit = 0,
    @enabled_for_syncmgr nvarchar(5) = 'false', /* Enabled for SYNCMGR: true or false */
	@ftp_address sysname = NULL,
	@ftp_port int = NULL,
	@ftp_login sysname = NULL,
	@ftp_password sysname = NULL
    ) AS

    SET NOCOUNT ON

    /*
    ** Declarations.
    */

    DECLARE @command nvarchar(4000)
    DECLARE @name nvarchar(255)
    DECLARE @retcode int
    DECLARE @subscription_type_id int   /* 1 = pull, 2 = anonymous */
	DECLARE @independent_agent_id bit
	DECLARE @distribution_agent nvarchar(100)
	DECLARE @category_name sysname
	DECLARE @platform_nt binary
	DECLARE @subscriber_enc_password sysname
	select @platform_nt = 0x1

    /*
    ** Security Check
    */

	EXEC @retcode = dbo.sp_MSreplcheck_subscribe
	IF @@ERROR <> 0 or @retcode <> 0
		RETURN(1)

    /*
    ** Initializations.
    */

	-- Set null @optional_command_line to empty string to avoid string concat problem
	if @optional_command_line is null
		set @optional_command_line = ''

	IF @distributor_password = N''
		select @distributor_password = [REDACTED]

	IF @ftp_password = N''
		select @ftp_password = [REDACTED]

    /*
    ** Parameter Check: @publisher
    ** Check to make sure that the publisher is define
    */
    IF @publisher IS NULL
    BEGIN
        RAISERROR (14043, 16, -1, '@publisher')
        RETURN (1)
    END

    EXECUTE @retcode = dbo.sp_validname @publisher

    IF @@ERROR <> 0 OR @retcode <> 0
       RETURN (1)
    

    /*
    ** Parameter Check: @publisher_db
    */

    IF @publisher_db IS NULL
    BEGIN
        RAISERROR (14043, 16, -1, '@publisher_db')
        RETURN (1)
    END

    EXECUTE @retcode = dbo.sp_validname @publisher_db

    IF @@ERROR <> 0 OR @retcode <> 0
       RETURN (1)

    /*
    ** Parameter Check: @publication
	** 
    */
    IF @publication IS NULL
    BEGIN
        RAISERROR (14043, 16, -1, '@publication')
        RETURN (1)
    END

    EXECUTE @retcode = dbo.sp_validname @publication

    IF @@ERROR <> 0 OR @retcode <> 0
       RETURN (1)

	/*
	** Parameter Check: @subscriber and @subscriber_db
	*/

	if @subscriber IS NULL or rtrim(@subscriber) = ''
		SELECT @subscriber = @@SERVERNAME

	if @subscriber_db IS NULL or rtrim(@subscriber_db) = ''
		SELECT @subscriber_db = DB_NAME()
	
	EXECUTE @retcode = dbo.sp_validname @subscriber
    IF @@ERROR <> 0 OR @retcode <> 0
       RETURN (1)
	
    EXECUTE @retcode = dbo.sp_validname @subscriber_db
    IF @@ERROR <> 0 OR @retcode <> 0
       RETURN (1)

    /* 
	** Check to see if MSreplictaion_subscriptions table exists.
	** If so, copy it into the temp table
	*/
	IF  NOT EXISTS (SELECT * FROM sysobjects WHERE 
		type = 'U' AND
		name = 'MSreplication_subscriptions')
	BEGIN
        RAISERROR (20017, 16, -1)
        RETURN (1)
	END	
	
	/*
    ** Check to make sure that the subscription does  exist
    */
    IF NOT EXISTS (SELECT * FROM  MSreplication_subscriptions
                WHERE UPPER(publisher) = UPPER(@publisher) AND
                      publisher_db  = @publisher_db AND
					  publication = @publication)
    BEGIN
        RAISERROR (20017, 16, -1)
        RETURN (1)
    END
	
	SELECT	@distribution_agent = NULL
	SELECT	@independent_agent_id = independent_agent, 
			@subscription_type_id = subscription_type,
			@distribution_agent = distribution_agent
		FROM  MSreplication_subscriptions
        WHERE UPPER(publisher) = UPPER(@publisher) AND
              publisher_db  = @publisher_db AND
			  publication = @publication
	/* Distribution agent for push subscriptions is at distributor side */
	IF @subscription_type_id = 0
	BEGIN
		RAISERROR (21001, 16, -1)
		RETURN (1)
	END

	IF @distribution_agent IS NOT NULL
	BEGIN
		RAISERROR (21002, 11, -1, @distribution_agent)
		RETURN (1)
	END

	-- Parameter check: @subscriber_security_mode
	if @subscriber_security_mode is null
	begin
		if ( platform() & @platform_nt ) = @platform_nt
			select @subscriber_security_mode = 1
		else
			select @subscriber_security_mode = 0
	end	

	if ( ( platform() & @platform_nt ) <> @platform_nt and @subscriber_security_mode = 1 )
	begin
		RAISERROR(21038, 16, -1)
		RETURN (1)
	end

	if (@subscription_type_id <> 0)
	begin
		if (@subscriber_security_mode = 0) and (@subscriber_login IS NULL or rtrim(@subscriber_login) = '')
		begin
			raiserror(3217, 16, -1, '@subscriber_login')
			return (1)
		end
	end
	
	IF NOT EXISTS (select * from sysobjects where name = 'MSsubscription_properties' and type = 'U')
	begin
		raiserror(14027, 16, -1, 'The subscription properties table ''MSsubscription_properties''')
		return (1)
	end

	/*
    ** Construct unique name
    */
    if @subscriber is NULL select @subscriber = ''
    if @subscriber_db is NULL select @subscriber_db = ''
	SELECT @name = CONVERT(nvarchar(23),@publisher ) + '-' + CONVERT(nvarchar(23),@publisher_db) + '-' + 
						CONVERT(nvarchar(23),@publication) + '-' + CONVERT(nvarchar(23),@subscriber) + '-' +
						CONVERT(nvarchar(23),@subscriber_db) + '- 0'

    BEGIN TRAN

    /*
    ** If the publication is independent agent type or it is the first
	** subscription on the non independent agent publications.
    */

	IF @independent_agent_id = 1 OR 
		NOT EXISTS (SELECT * FROM MSreplication_subscriptions WHERE
 				            UPPER(@publisher) = UPPER(publisher) and
				            @publisher_db = publisher_db and
                            agent_id IS NOT NULL and
				            independent_agent = 0)
    BEGIN
        
		/* Construct agent command */
		SELECT @command = '-Publisher ' + @publisher + ' '
		SELECT @command = @command + '-PublisherDB ' + QUOTENAME(@publisher_db) + ' '
		IF @independent_agent_id = 1
			SELECT @command = @command + '-Publication ' + QUOTENAME(@publication) + ' '

		SELECT @command = @command + '-Distributor ' + QUOTENAME(@distributor)  + ' '

		/*
		Use -Xdatabase to save command line space
		We can not use -Xserver for distribution because SQLExec will valid the server
		to be in sysservers.

		SELECT @command = @command + '-DistributionDB ' + QUOTENAME(@distribution_db)  + ' '
		*/
		
		SELECT @command = @command + '-SubscriptionType ' + convert(nvarchar(10),@subscription_type_id)  + ' '
		SELECT @command = @command + '-Subscriber ' + QUOTENAME(@subscriber)  + ' '
	
		select @command = @command + '-SubscriberSecurityMode ' + 
			convert(nvarchar(10),@subscriber_security_mode) + ' '
		if @subscriber_login is not NULL
			select @command = @command + '-SubscriberLogin ' + quotename(@subscriber_login) + ' '
		if @subscriber_password is not NULL
		begin
			set @subscriber_enc_password = [REDACTED]
			exec @retcode = master.dbo.xp_repl_encrypt @subscriber_enc_password OUTPUT
			select @command = @command + '-SubscriberEncryptedPassword ' + quotename(@subscriber_enc_password) + ' '
		end

		SELECT @command = @command + '-SubscriberDB ' + QUOTENAME(@subscriber_db) + ' '

		/* 
		** make sure the command line is not truncated
		*/
		/* Use datalength because len doesn't count the last space in @command */
		IF (datalength(@command) + datalength(@optional_command_line)) > 8000
		BEGIN
			RAISERROR(20018, 16, -1)
			RETURN(1)
		END

		SELECT @command = @command + @optional_command_line

		-- Get Distribution category name (assumes category_id = 10)
		select @category_name = name FROM msdb.dbo.syscategories where category_id = 10

		EXEC @retcode = dbo.sp_MSadd_repl_job
				   @name = @name,
				@subsystem = 'Distribution',
				  @server = @@SERVERNAME,
				   @databasename = @distribution_db,
				@enabled = 1,
			   @freqtype = @frequency_type,
			   @freqinterval = @frequency_interval,
			   @freqsubtype = @frequency_subday,
			   @freqsubinterval = @frequency_subday_interval,
			   @freqrelativeinterval = @frequency_relative_interval,
			   @freqrecurrencefactor = @frequency_recurrence_factor,
			   @activestartdate = @active_start_date,
			   @activeenddate = @active_end_date,
			   @activestarttimeofday = @active_start_time_of_day,
			   @activeendtimeofday = @active_end_time_of_day,
				@command = @command,
				@category_name = @category_name,
				@retryattempts = 10,
				@retrydelay = 1,
				@job_id = @distribution_jobid OUTPUT

		IF @@ERROR <> 0 or @retcode <> 0
		BEGIN
			IF @@TRANCOUNT = 1
				ROLLBACK TRAN
			ELSE
				COMMIT TRAN   
			RETURN(1)
		END
	END

	if (@subscription_type_id = 1) OR (@subscription_type_id = 2)
	BEGIN
		IF NOT EXISTS (select * from MSsubscription_properties 
            where UPPER(publisher) = UPPER(@publisher)
			  and publisher_db =  @publisher_db
			  and publication = @publication) 
		BEGIN
			-- 0  transactional
			-- 1  snapshot
			-- 2  merge
			IF (@encrypted_distributor_password = 0)
			-- Encrypt the password
			BEGIN
				EXEC @retcode = master.dbo.xp_repl_encrypt @distributor_password OUTPUT
				IF @@error <> 0 OR @retcode <> 0
					return 1
			END
	
			INSERT INTO MSsubscription_properties 
			(publisher, publisher_db, publication, publication_type, 
			 publisher_login,publisher_password, publisher_security_mode, 
			 distributor, distributor_login, distributor_password, 
			 distributor_security_mode, ftp_address, ftp_port, ftp_login, 
			 ftp_password)
			values (@publisher, @publisher_db, @publication, 0,	NULL, NULL, 1, 
				@distributor, @distributor_login, @distributor_password, 
				@distributor_security_mode, @ftp_address, @ftp_port, @ftp_login,
				@ftp_password)
			IF @@ERROR <> 0 
			BEGIN
				IF @@TRANCOUNT = 1
					ROLLBACK TRAN
				ELSE
					COMMIT TRAN           
				RETURN(1)
			END
		END
		ELSE
		BEGIN
			update MSsubscription_properties set
				distributor = @distributor,
				distributor_login = @distributor_login,
				distributor_password = [REDACTED]
				distributor_security_mode = @distributor_security_mode
				where UPPER(publisher) = UPPER(@publisher)
					and publisher_db =  @publisher_db
					and publication = @publication
		END
		IF @@ERROR <> 0 
		BEGIN
			IF @@TRANCOUNT = 1
				ROLLBACK TRAN
			ELSE
				COMMIT TRAN           
			RETURN(1)
		END
	END


	/* If we do not have independent agents , i.e. independent_agent=0, but there is
	already a row for that publisher and that publisher database with a NOT null 
	distribution_agent_id, then set the @distribution_jobid to that id.  Note that if
	there are no rows returned, the value of the variable does not change, which is what we want.
	There should never be more than one row ever returned for this query - but will use TOP 1
	to insist that is the case.
	*/

	SELECT DISTINCT @distribution_jobid=agent_id FROM MSreplication_subscriptions
	WHERE UPPER(publisher) = UPPER(@publisher) AND publisher_db =  @publisher_db
	AND agent_id IS NOT NULL AND independent_agent=0
	
	UPDATE MSreplication_subscriptions SET distribution_agent = @name,
		agent_id = @distribution_jobid
		WHERE UPPER(publisher) = UPPER(@publisher) AND 
			publisher_db =  @publisher_db AND 
			publication =  @publication AND 
			(subscription_type = 1 /* pull*/ OR subscription_type = 2) /*anonymous*/

    IF @@ERROR <> 0 
    BEGIN
		IF @@TRANCOUNT = 1
			ROLLBACK TRAN
		ELSE
			COMMIT TRAN           
		RETURN(1)
    END

	/* Conditional support for MobileSync */
    if LOWER(@enabled_for_syncmgr) = 'true'
    BEGIN
		/* Call sp_MSregistersubscription so that the subscription can be synchronized via MobileSync etc. */
		declare @subscription_id uniqueidentifier
		set @subscription_id = convert(uniqueidentifier, @distribution_jobid)

		exec @retcode = dbo.sp_MSregistersubscription @replication_type = 1,
									@publisher = @publisher,
									@publisher_db = @publisher_db,
									@publication = @publication,
								    @subscriber = @subscriber,
								    @subscriber_db = @subscriber_db,
									@subscriber_security_mode = @subscriber_security_mode,
									@subscriber_login = @subscriber_login,
									@subscriber_password = [REDACTED]
									@distributor = @distributor,
								    @subscription_id = @subscription_id,
									@independent_agent = @independent_agent_id,
									@subscription_type = @subscription_type_id
		IF @@ERROR <> 0 or @retcode <> 0
	    BEGIN
			IF @@TRANCOUNT = 1
				ROLLBACK TRAN
			ELSE
				COMMIT TRAN           
			RETURN(1)
	    END
	END

    COMMIT TRAN
	RETURN(0)
GO


raiserror('Creating procedure sp_helpsubscription_properties', 0,1)
go
CREATE PROCEDURE sp_helpsubscription_properties
        @publisher sysname = '%', 
		@publisher_db sysname = '%', 
		@publication sysname = '%', 
		@publication_type int = NULL
    AS

    SET NOCOUNT ON

	declare @retcode int

	/*
    ** Security Check
    */

	EXEC @retcode = dbo.sp_MSreplcheck_subscribe
	IF @@ERROR <> 0 or @retcode <> 0
		RETURN(1)

	/*
	** The logic is added here for the case where MSsubscription_properties table does not exist
	** or relevant entry is not added because sp_addmergepullsubscription_agent or sp_addsubscription_agent
	** is not called.
	*/
	IF NOT EXISTS (select * from sysobjects where name = 'MSsubscription_properties' and type = 'U')
	begin
		return (0)
	end

	IF (@publication IS NULL) OR (@publication = '')
		select @publication = '%'

	IF @publication_type IS NULL
	BEGIN
		select publisher, publisher_db, publication, publication_type, publisher_login,
			publisher_password, publisher_security_mode, distributor, distributor_login,
			distributor_password, distributor_security_mode, ftp_address, isnull(ftp_port, 0),
			ftp_login, ftp_password
	 	from MSsubscription_properties
			where ((@publisher = N'%') or (UPPER(publisher) = UPPER(@publisher)))
			and publisher_db like @publisher_db
			and publication like @publication
	END
	ELSE
	BEGIN
		select publisher, publisher_db, publication, publication_type, publisher_login,
			publisher_password, publisher_security_mode, distributor, distributor_login,
			distributor_password, distributor_security_mode, ftp_address, isnull(ftp_port, 0),
			ftp_login, ftp_password
		from MSsubscription_properties
			where ((@publisher = N'%') or (UPPER(publisher) = UPPER(@publisher)))
			and publisher_db like @publisher_db
			and publication like @publication
			and publication_type = @publication_type
	END	

	return (0)
GO

EXEC dbo.sp_MS_marksystemobject sp_helpsubscription_properties
GO

raiserror('Creating procedure sp_change_subscription_properties', 0,1)
go
CREATE PROCEDURE sp_change_subscription_properties
        @publisher sysname, 
		@publisher_db sysname, 
		@publication sysname, 
		@property sysname,
		@value sysname
    AS

    SET NOCOUNT ON

	DECLARE @command nvarchar(2000)
	DECLARE @column_to_update nvarchar(64)
	DECLARE @value_string nvarchar(255)
	DECLARE @retcode int

	/*
    ** Security Check
    */

	EXEC @retcode = dbo.sp_MSreplcheck_subscribe
	IF @@ERROR <> 0 or @retcode <> 0
		RETURN(1)

	IF NOT EXISTS (select * from sysobjects where name = 'MSsubscription_properties' and type = 'U')
	begin
		raiserror(14027, 16, -1, 'The subscription properties table ''MSsubscription_properties''')
		return (1)
	end
	
	if (@publisher is null)
	begin
		raiserror(14043, 16, -1, '@publisher')
		return (1)
	end

	if(@publisher_db is null)
	begin
		raiserror(14043, 16, -1, '@publisher_db')
		return (1)
	end
	
	IF (@property IS NULL)
	begin
		raiserror(14043, 16, -1, '@property')
		return (1)
	end
	ELSE IF (lower(@property) = 'publisher_login')
		select @column_to_update = 'publisher_login'
	ELSE IF (lower(@property) = 'publisher_password')
	begin
		select @column_to_update = 'publisher_password'
		EXEC @retcode = master.dbo.xp_repl_encrypt @value OUTPUT
		IF @@error <> 0 OR @retcode <> 0
			return 1
	end
	ELSE IF (lower(@property) = 'publisher_security_mode')
		select @column_to_update = 'publisher_security_mode'
	ELSE IF (lower(@property) = 'distributor')
		select @column_to_update = 'distributor'
	ELSE IF (lower(@property) = 'distributor_login')
		select @column_to_update = 'distributor_login'
	ELSE IF (lower(@property) = 'distributor_password')
	begin
		select @column_to_update = 'distributor_password'
		EXEC @retcode = master.dbo.xp_repl_encrypt @value OUTPUT
		IF @@error <> 0 OR @retcode <> 0
			return 1
	end
	ELSE IF (lower(@property) = 'distributor_security_mode')
		select @column_to_update = 'distributor_security_mode'
	ELSE IF (lower(@property) = 'ftp_address')
		select @column_to_update = 'ftp_address'
	ELSE IF (lower(@property) = 'ftp_port')
		select @column_to_update = 'ftp_port'
	ELSE IF (lower(@property) = 'ftp_login')
		select @column_to_update = 'ftp_login'
	ELSE IF (lower(@property) = 'ftp_password')
		select @column_to_update = 'ftp_password'
	ELSE
	BEGIN
		raiserror (3217, 16, -1, '@property')
		return(1)
	END



	IF (lower(@property) = 'distributor_security_mode') OR (lower(@property) = 'publisher_security_mode') 
	BEGIN
		IF NOT ( @value = 0 or @value = 1 or (@value = 2 and lower(@property) = 'publisher_security_mode' )) 
		BEGIN
			raiserror(3217, 16, -1, '@value')
			return(1)
		END
		select @value_string = convert(nvarchar(1), @value)
	END
	ELSE
	BEGIN
		IF (@value IS NULL)
			select @value_string = 'NULL'
		ELSE
			select @value_string = 'N''' + rtrim(@value) + ''''
	END

	if (@publication is null) or (@publication = '')
	begin
		select @publication = '%'
	end
	
	-- Password is encrypted. Cannot use dynamic query (exec (@cmd)) to update
	-- otherwise, the chars will be convert to '???'
	IF (lower(@property) = 'distributor_password')
	begin
		update MSsubscription_properties set distributor_password = [REDACTED] where 
			UPPER(publisher) = UPPER(@publisher) and 
			publisher_db = @publisher_db and
			publication like @publication 
	end
	ELSE IF (lower(@property) = 'publisher_password')
	begin
		update MSsubscription_properties set publisher_password = [REDACTED] where 
			UPPER(publisher) = UPPER(@publisher) and 
			publisher_db = @publisher_db and
			publication like @publication 
	end
	else
	begin
		select @command = N'update MSsubscription_properties set ' + @column_to_update + '= ' + @value_string
				+ ' where UPPER(publisher) = UPPER(''' + @publisher 
				+ ''') and publisher_db = ''' + @publisher_db
				+ ''' and publication like ''' + @publication + ''''
		EXEC (@command)
	end
		
	if @@error <> 0
		return (1)
	else
		return (0)

GO
EXEC dbo.sp_MS_marksystemobject sp_change_subscription_properties
GO
grant execute on dbo.sp_change_subscription_properties to public

raiserror('Creating procedure sp_MSget_pullsubsagent_owner', 0,1)
go

CREATE PROCEDURE sp_MSget_pullsubsagent_owner (
    @publisher    sysname,
    @publisher_db sysname,
    @publication  sysname,   /* publication name */
    @owner_sid    varbinary(85) OUTPUT 
    ) AS

    declare @job_id uniqueidentifier
    set nocount on

    select @owner_sid = null
        

    if exists (select * from sysobjects 
               where type = 'U' and 
                     name = 'MSreplication_subscriptions')
    begin 
        -- Get the job_id corresponding to the publication
        select @job_id = agent_id
        from MSreplication_subscriptions
        where upper(@publisher) = upper(publisher) and
            @publisher_db = publisher_db and
            @publication = publication 

        -- Using the job_id in MSsubscription properties to get the owner_sid 
        -- in msdb..sysjobs    
        select @owner_sid = owner_sid
        from  msdb..sysjobs
        where @job_id = job_id
    end            
go 

exec dbo.sp_MS_marksystemobject 'sp_MSget_pullsubsagent_owner'

raiserror('Creating procedure sp_droppullsubscription', 0,1)
go

CREATE PROCEDURE sp_droppullsubscription (
    @publisher sysname,
    @publisher_db sysname,
    @publication sysname,   /* publication name */
    @reserved bit = 0
    ) AS

    SET NOCOUNT ON

    /*
    ** Declarations.
    */


    DECLARE @name nvarchar(255)
    DECLARE @retcode int
    DECLARE @agent_id binary(16)
    DECLARE @publisher_ex sysname          /* Expression used in the cursor */
    DECLARE @publisher_db_ex sysname     /* Expression used in the cursor */
    DECLARE @publication_ex sysname      /* Expression used in the cursor */
	DECLARE @expanded bit
	DECLARE @subscription_type_id int
	DECLARE @count_sub int
	DECLARE @drop_null_pub bit
	DECLARE @drop_push_bit bit
	DECLARE @push int
	DECLARE @implicit_transaction int
	DECLARE @close_cursor_at_commit int
    DECLARE @owner_sid varbinary(85)
    DECLARE @owner_name sysname
    DECLARE @qualified_publication_name nvarchar(512)
	
	/* 
	** Initialization
	*/
	SELECT @expanded = 0
	SELECT @drop_null_pub = 0
	SELECT @push = 0

	/*
	** Get the original set value off IMPLICIT_TRANSACTIONS and CURSOR_CLOSE_ON_COMMIT
	**  	before set these two to off
	*/
	select @implicit_transaction = 0
	select @close_cursor_at_commit = 0
	IF (@reserved = 0)
	BEGIN
		SELECT @implicit_transaction = @@options & 2
		SELECT @close_cursor_at_commit = @@options & 4
		SET IMPLICIT_TRANSACTIONS OFF
		SET CURSOR_CLOSE_ON_COMMIT OFF
	END

    /*
    ** Security Check
    */

	EXEC @retcode = dbo.sp_MSreplcheck_subscribe
	IF @@ERROR <> 0 or @retcode <> 0
		RETURN(1)

	SELECT @drop_push_bit = 0	
    
    /*
    ** Check parameter and set expressions used by cursor
    */
    
    /* Publisher */
    IF @publisher IS NULL
    BEGIN
		RAISERROR (14043, 16, -1, '@publisher')
		RETURN (1)
    END

    IF @publisher = 'all'
    BEGIN
        SELECT @publisher_ex = '%'
        SELECT @expanded = 1
    END
    ELSE
    BEGIN
        EXECUTE @retcode = dbo.sp_validname @publisher
        IF @retcode <> 0
        RETURN (1)
        SELECT @publisher_ex = @publisher
    END


    /* Publisher_db */
    IF @publisher_db IS NULL
    BEGIN
            RAISERROR (14043, 16, -1, '@publisher_db')
            RETURN (1)
    END

    IF @publisher_db = 'all'
    BEGIN
        SELECT @publisher_db_ex = '%'
        select @expanded = 1
    END
    ELSE
    BEGIN
		/*
        EXECUTE @retcode = dbo.sp_validname @publisher_db
        IF @retcode <> 0
        RETURN (1)
		*/
        SELECT @publisher_db_ex = @publisher_db
    END

    /* 
	** Publication
	** '' is not a valid name but it may be in the publication name in the table. 
	*/
    IF @publication IS NULL OR @publication = ''
    BEGIN
		SELECT @drop_null_pub = 1
    END
    ELSE IF @publication = 'all'
    BEGIN
        SELECT @publication_ex = '%'
        SELECT @expanded = 1
		SELECT @drop_null_pub = 1
    END
    ELSE
    BEGIN
        EXECUTE @retcode = dbo.sp_validname @publication
        IF @retcode <> 0
        RETURN (1)
        SELECT @publication_ex = @publication
    END

    /*
    ** Check to see if the  subscription table exists
    */
    IF NOT EXISTS (SELECT * FROM sysobjects 
                WHERE type = 'U' AND
                      name = 'MSreplication_subscriptions')
    BEGIN
		IF @expanded = 0
		BEGIN
			RAISERROR(14135, 11, -1,  @publisher, 
				@publisher_db, @publication)
			RETURN(1)
		END
		ELSE
			RETURN(0)
    END

	IF @expanded = 0 
	BEGIN 
		/*
		**
		** Check to see if the subscription entry exists
		*/
		IF  NOT EXISTS (SELECT * FROM  MSreplication_subscriptions 
					WHERE UPPER(publisher) = UPPER(@publisher) AND
					  publisher_db = @publisher_db AND
					  publication = @publication)     
		BEGIN
			RAISERROR(14135, 11, -1, @publisher, @publisher_db, @publication)
			RETURN(1)
		END

		/* 
		** Make sure the subscription is not push type if @drop_push_bit = 0
		*/
    	IF @drop_push_bit = 0
		BEGIN
			IF EXISTS (SELECT * FROM MSreplication_subscriptions 
				WHERE UPPER(publisher) = UPPER(@publisher) AND
				  publisher_db = @publisher_db AND
				  publication = @publication AND
				  subscription_type = @push AND
				  @drop_push_bit = 0)
			BEGIN
				RAISERROR(20017, 16, -1)
				RETURN(1)
			END
		END

	END
	ELSE
	/* 
	** Open a cursor and call recursively if
	** parameters are expanded.
	*/
	BEGIN

		/*		
		**  Note: Any expression check on null value is false
		** @subscription_type_id is NULL <==> push
		** @subscription_type_id is NOT NULL <==> non push
		*/
		DECLARE hCdroppullsubscription CURSOR LOCAL FAST_FORWARD FOR
			SELECT DISTINCT publisher, publisher_db, publication    
				FROM MSreplication_subscriptions
				WHERE ((@publisher_ex = N'%') OR (UPPER(publisher) = UPPER(@publisher_ex))) AND
					  publisher_db LIKE @publisher_db_ex AND
					  (publication LIKE @publication_ex OR
					  (@drop_null_pub = 1 AND
					  publication IS NULL)) AND
					  ((@drop_push_bit =0 AND
					  subscription_type <> @push) OR
					  @drop_push_bit = 1)
		FOR READ ONLY
		OPEN hCdroppullsubscription

		FETCH hCdroppullsubscription INTO @publisher, 
			@publisher_db, @publication
		WHILE (@@fetch_status <> -1)
		BEGIN
			EXECUTE @retcode  = dbo.sp_droppullsubscription @publisher = @publisher, 
				@publisher_db = @publisher_db, @publication = @publication, 
				@reserved = 1

			FETCH hCdroppullsubscription INTO @publisher, 
				@publisher_db, @publication
		END

		CLOSE hCdroppullsubscription
		DEALLOCATE hCdroppullsubscription
		RETURN (0)
	END
	
    /*
    ** Only members of the sysadmin group and the creator of the distribution
    ** agent can drop a pull subscription successfully. This behavior matches 
    ** the behavior of the sysjobs_view. DBO of the subscriber database, 
    ** sysadmins (owner is undefined) can drop a subscription if the owner_sid 
    ** is null.
    */

    EXEC sp_MSget_pullsubsagent_owner @publisher = @publisher,
                                      @publisher_db = @publisher_db,
                                      @publication = @publication,
                                      @owner_sid = @owner_sid OUTPUT

    IF (@owner_sid is not null AND
        (SUSER_SID() <> @owner_sid) AND
        (ISNULL(IS_SRVROLEMEMBER('sysadmin'),0) = 0))
    BEGIN
        SELECT @owner_name = SUSER_SNAME(@owner_sid)
        SELECT @qualified_publication_name = @publisher + N':' + 
                                             @publisher_db + N':' +
                                             @publication
        RAISERROR(21121,16,-1,@owner_name, @qualified_publication_name) 
        RETURN (1)
    END

	/* 
	** Get the agent name, it may be dropped later.
	*/
    SELECT @agent_id = agent_id FROM MSreplication_subscriptions
                    WHERE UPPER(publisher) = UPPER(@publisher) AND
                          publisher_db  = @publisher_db AND
                          publication = @publication 


	begin tran
    save TRAN droppullsubscription

	/*
	** Drop the subscription entry and the distribution agent if it exists 
	*/


	/* 
	** If the distribution agent is not used anymore,
	** drop the agent if it exists
	*/

    IF @agent_id IS NOT NULL
    BEGIN
    	IF (EXISTS (SELECT * FROM msdb..sysjobs_view WHERE job_id = @agent_id))
    	BEGIN
       		 EXEC @retcode = msdb.dbo.sp_delete_job @job_id = @agent_id
        	 IF @@ERROR <> 0 or @retcode <> 0
				GOTO UNDO

			-- Delete MSreplication_subsciptions table after dropping 
			-- the distribution agent and delay one second
			-- to avoid deadlock with it.
			WAITFOR DELAY '00:00:01'
		END

    END

	/* Call sp_MSunregistersubscription so that the reg entries get deleted */
	declare @subscriber_db sysname
	set @subscriber_db = DB_NAME()
	exec @retcode = dbo.sp_MSunregistersubscription @publisher = @publisher,
								@publisher_db = @publisher_db,
								@publication = @publication,
							    @subscriber = @@SERVERNAME,
							    @subscriber_db = @subscriber_db

	IF @retcode<>0 or @@ERROR<>0
		GOTO UNDO
	/*
	-- Delete MSreplication_subsciptions table after dropping the distribution agent\
	-- To avoid deadlock with it.
	--DELETE MSreplication_subscriptions WHERE UPPER(publisher) = UPPER(@publisher)	AND
		--publisher_db  = @publisher_db AND
		--publication = @publication 
	
	--IF @@ERROR <> 0 
	--	GOTO UNDO

	*/

	IF EXISTS(select * from sysobjects where type='U' and name = 'MSsubscription_properties')
	BEGIN
		DELETE FROM MSsubscription_properties 
		WHERE UPPER(publisher) = UPPER(@publisher)	AND
		publisher_db  = @publisher_db AND
		publication = @publication 

		IF @@ERROR <> 0 
			GOTO UNDO

		IF NOT EXISTS (SELECT * FROM MSsubscription_properties)
		BEGIN
			DROP TABLE MSsubscription_properties
			IF @@ERROR <> 0 
				GOTO UNDO
		END
	END
	
	/*
	** Clean up metadata at subscriber side
	*/
	exec @retcode = dbo.sp_subscription_cleanup @publisher = @publisher,
											@publisher_db  = @publisher_db,
											@publication = @publication
	IF @retcode<>0 or @@ERROR<>0
		GOTO UNDO

	IF NOT EXISTS (SELECT * FROM MSreplication_subscriptions)
	BEGIN
		DROP TABLE MSreplication_subscriptions
		IF @@ERROR <> 0 
			GOTO UNDO
	END
	

    COMMIT TRAN
	/*
	** set back the two settings if needed 
	*/
	if @reserved = 0
	BEGIN
		IF @implicit_transaction <>0 
			SET IMPLICIT_TRANSACTIONS ON
		IF @close_cursor_at_commit <>0 
			SET CURSOR_CLOSE_ON_COMMIT ON
	END
	RETURN (0)

UNDO:
    IF @@TRANCOUNT > 0
	begin
        ROLLBACK TRAN droppullsubscription
        COMMIT TRAN   
	end
	/*
	** set back the two settings if needed
	*/
	if @reserved = 0
	BEGIN
		IF @implicit_transaction <>0 
			SET IMPLICIT_TRANSACTIONS ON
		IF @close_cursor_at_commit <>0 
			SET CURSOR_CLOSE_ON_COMMIT ON
	END

	return 1
go
 

raiserror('Creating procedure sp_helppullsubscription', 0,1, 0,1)
go

CREATE PROCEDURE sp_helppullsubscription (
    @publisher sysname = '%',
    @publisher_db sysname = '%',
    @publication sysname = '%',
	@show_push nvarchar(5) = 'false'
    ) AS

    SET NOCOUNT ON

    /*
    ** Declarations.
    */


    DECLARE @command nvarchar(255)
    DECLARE @name nvarchar(255)
	DECLARE @retcode int
	DECLARE @show_push_bit bit
	DECLARE @push int
	declare @subscriber			sysname
	declare @subscriber_db		sysname
	declare @publisher_local	sysname
	declare @publisher_db_local	sysname
	declare @publication_local	sysname
	declare @subscription_name 	nvarchar(1000)
	declare @regkey				nvarchar(1000)
	declare @syncmgr_keyexist				int
	declare @helpsubscriptioncursor_open	int


	SELECT @push = 0

    /*
    ** Security Check
    */

	EXEC @retcode = dbo.sp_MSreplcheck_subscribe
	IF @@ERROR <> 0 or @retcode <> 0
		RETURN(1)

    /*
    ** Initializations.
    */
	set @subscriber = @@SERVERNAME	 
	set @subscriber_db = DB_NAME()

    /*
    ** Parameter Check: @publisher
    ** Check to make sure that the publisher is define
    */
    IF @publisher IS NULL
    BEGIN
        RAISERROR (14043, 16, -1, '@publisher')
        RETURN (1)
    END

    IF @publisher <> '%' 
    BEGIN
		EXECUTE @retcode = dbo.sp_validname @publisher

    	IF @@ERROR <> 0 OR @retcode <> 0
       		RETURN (1)
    END

    IF @publication <> '%' 
    BEGIN
		EXECUTE @retcode = dbo.sp_validname @publication

    	IF @@ERROR <> 0 OR @retcode <> 0
       		RETURN (1)
    END


	IF @show_push IS NOT NULL AND 
		LOWER(@show_push) NOT IN ('true', 'false')
    BEGIN
        RAISERROR (14148, 16, -1, '@show_push')
        RETURN (1)
    END

	IF LOWER(@show_push) = 'false'				
		SELECT @show_push_bit = 0	
    IF LOWER(@show_push) = 'true'	
		SELECT @show_push_bit = 1


	IF NOT EXISTS (SELECT * FROM sysobjects WHERE 
		type = 'U' AND
		name = 'MSreplication_subscriptions')
		RETURN (0)

	create table #helpsubscription
				(
					publisher 				sysname 	NOT NULL,
			        publisher_db 			sysname 	NOT NULL, 
		        	publication 			sysname 	NULL, 
					independent_agent 		bit 		NOT NULL,
			        subscription_type 		int 		NOT NULL,
			        distribution_agent 		nvarchar(100) NULL, 
					time 					smalldatetime NOT NULL,
					description 			nvarchar(255) NULL,
			        transaction_timestamp 	varbinary(16) NOT NULL,
					-- SyncTran
					update_mode 			tinyint 	NOT NULL,
					agent_id 				binary(16) 	NULL,
					subscription_guid 		binary(16) 	NULL,
					subid 					binary(16) 	NULL,
					immediate_sync 			bit 		NOT NULL,
					enabled_for_syncmgr		int			NULL			
				)
				
	insert into #helpsubscription
        select *, 0 from MSreplication_subscriptions
                WHERE ((@publisher = N'%') OR (UPPER(publisher) = UPPER(@publisher))) AND
                      publisher_db  LIKE @publisher_db AND
                      publication LIKE @publication AND
					  (subscription_type <> @push OR
					   @show_push_bit = 1)
        ORDER BY publisher, publisher_db, publication

	declare #helpsubscriptioncursor CURSOR LOCAL FAST_FORWARD FOR 
		select DISTINCT publisher, publisher_db, publication
       	FROM #helpsubscription
			FOR READ ONLY
	create table #syncmgr_keyexist (syncmgr_keyexist int)
	open #helpsubscriptioncursor
	select @helpsubscriptioncursor_open = 1					
	fetch next from #helpsubscriptioncursor into @publisher_local, @publisher_db_local, @publication_local
	while (@@fetch_status <> -1)
		begin
			set @subscription_name = @publisher_local + ':' + @publisher_db_local + ':' + @publication_local + ':' + @subscriber + ':' + @subscriber_db
			/* Replace back slash with forward slash so that the key name is a valid REGISTRY key name */
			set @subscription_name = REPLACE(@subscription_name,'\','/')
			set @regkey = 'SOFTWARE\Microsoft\MSSQLServer\Replication\Subscriptions\' + @subscription_name
			insert into #syncmgr_keyexist EXECUTE master.dbo.xp_regread 'HKEY_LOCAL_MACHINE', @regkey
			select @syncmgr_keyexist = syncmgr_keyexist from #syncmgr_keyexist
			update #helpsubscription set enabled_for_syncmgr = @syncmgr_keyexist 
				where UPPER(publisher) = UPPER(@publisher_local)
					and publisher_db = @publisher_db_local
					and publication = @publication_local
				
			fetch next from #helpsubscriptioncursor into @publisher_local, @publisher_db_local, @publication_local
		end


    /*
    ** Get the result
	**
	** Note: have to return meta data
    */
    SELECT  'publisher'				= publisher,
            'publisher database'	= publisher_db,
            'publication'			= publication,
			'independent_agent'		= independent_agent,
            'subscription type'     = subscription_type,
            'distribution agent'	= distribution_agent,
			'publication description'   = description,
			'last updating time'		= convert(nvarchar(12), time, 112) + 
                                          substring(convert(nvarchar(24), time, 121), 11,13),
			'subscription_name'	  	= publisher + ':' + publisher_db + ':' + publication,
			'last transaction timestamp' = transaction_timestamp,
			-- SyncTran
			'update_mode'         = update_mode,
			'distribution agent job_id' = agent_id,
			'enabled for syncmgr' = enabled_for_syncmgr,
			'subscription guid' = subscription_guid,
			'subid ' = subid,
			'immediate_sync' = immediate_sync
        FROM #helpsubscription

	drop table #helpsubscription
	if (@helpsubscriptioncursor_open = 1)
		begin
			close #helpsubscriptioncursor
			deallocate #helpsubscriptioncursor
		end			
	drop table #syncmgr_keyexist	
			
        
GO


raiserror('Creating procedure sp_MStable_has_unique_index', 0,1)
go

create procedure sp_MStable_has_unique_index @tabid int
as
begin

	/* 
	** Returns id of unique index, if it exists, else 0
	*/
	declare @indid int

	if (ObjectProperty(@tabid, 'IsTable') = 1) and (ObjectProperty(@tabid, 'TableHasIndex') = 1)
	begin
        -- First get the primary index id. See bug 52471
		select @indid = i.indid from sysindexes i where 
            -- get the primary key index
            (i.status & 2048) <> 0
			and i.id = @tabid

        if @indid is null
        begin
            -- Get the first unique index
		    select top 1 @indid = i.indid from sysindexes i where 
                (i.status & 2) <> 0
			    and i.id = @tabid
                order by i.indid asc
        end
		if @indid is null select @indid = 0
	end
	else
		select @indid = 0

	return @indid
end
go

raiserror('Creating procedure sp_MSchange_priority', 0,1)
GO

-- @value has to be unicode too.

CREATE PROCEDURE sp_MSchange_priority (@subid uniqueidentifier, @value nvarchar(255))
as
	update sysmergesubscriptions set priority = convert(real, @value)
	       where subid = @subid
go
exec dbo.sp_MS_marksystemobject sp_MSchange_priority 
go
grant execute on dbo.sp_MSchange_priority to public

raiserror('Creating procedure sp_expired_subscription_cleanup', 0,1)
GO
 
CREATE PROCEDURE sp_expired_subscription_cleanup
AS
declare @retcode 		int
declare @publisher_db	sysname
declare @category		int
declare @proc_name		nvarchar(200)
declare @distributor 	sysname
declare @distribdb		sysname
declare @distproc		nvarchar(270)
/*
** Security Check
*/
	EXEC @retcode = dbo.sp_MSreplcheck_publish
	IF @@ERROR <> 0 or @retcode <> 0
		return (1)
	/*
	** Get distribution server information for remote RPC call.
	*/

EXECUTE @retcode = sp_helpdistributor @rpcsrvname = @distributor OUTPUT,
     @distribdb   = @distribdb OUTPUT
IF @@ERROR <> 0 or @retcode <> 0
    BEGIN
        RAISERROR (20036, 16, -1)
        return (1)
    END
	
		
DECLARE DC CURSOR LOCAL FAST_FORWARD for select DISTINCT name, category from master..sysdatabases 
	where (category & 4) = 4 or (category & 1 = 1)
	for read only
	open DC
	fetch DC into @publisher_db, @category
	WHILE (@@fetch_status <> -1)
	BEGIN
		if (@category & 4 = 4)
			begin
				select @proc_name = @publisher_db + '.dbo.sp_MSdrop_expired_mergesubscription'
				exec @retcode = @proc_name
				if @retcode<>0 or @@ERROR<>0
					goto DONE
			end
		if (@category & 1 = 1)
			begin
				select @proc_name = @publisher_db + '.dbo.sp_MSdrop_expired_subscription'
				exec @retcode = @proc_name
				if @retcode<>0 or @@ERROR<>0
					goto DONE
			end	
	fetch DC into @publisher_db, @category
	END

	/*
	** sp_MScleanup_agent_entry in distribution database is called to periodically remove obselete
	** entries in MSmerge_agents, which may be caused by the following reasons:
	**  1. publishing database is externally removed; therefore cleanup agent can not do its job
	**  2. Entries for anonymous merge subscriptions
	*/
	SELECT @distproc = RTRIM(@distributor) + '.' + RTRIM(@distribdb) + '..sp_MScleanup_agent_entry'
	exec @retcode = @distproc 
	if @@ERROR<>0 or @retcode<>0
	BEGIN
		close DC
		deallocate DC
    	return (1)
    END

DONE:
	close DC
	deallocate DC
GO

go
exec dbo.sp_MS_marksystemobject sp_expired_subscription_cleanup
go
grant execute on dbo.sp_expired_subscription_cleanup to public


raiserror('Creating procedure sp_addmergepullsubscription', 0,1)
GO
 
CREATE PROCEDURE sp_addmergepullsubscription (
	@publication 			sysname,	      			/* Publication name */
	@publisher				sysname = @@SERVERNAME,  	/* Publisher server */
	@publisher_db			sysname = NULL,  			/* Publication database */
	@subscriber_type 		nvarchar(15) = 'local',			/* Subscriber type */ 
	@subscription_priority 	real 		= NULL,				/* Subscription priority */
    @sync_type 				nvarchar(15) = 'automatic', /* subscription sync type */
	@description nvarchar(255) = NULL			  
 	) AS

    SET NOCOUNT ON

    /*
    ** Declarations.
    */
    declare @retcode				int
    declare	@subscriber_db			sysname
    declare @subnickname			int
    declare @subscriber_srvid		int 
    declare @publisher_srvid		int 
    declare @priority 				real
    declare @subid	 				uniqueidentifier
    declare @subscriber_typeid 		smallint
    declare @subscription_type	 	smallint
    declare @command 				nvarchar(255)
    declare @inactive				tinyint 
	declare @global 				tinyint		/* subscriber type is global */
	declare @push 					tinyint		/* subscription type is push */
	 
    declare @sync_typeid 			tinyint
	declare @nosync 				tinyint		
	declare @automatic				tinyint			 
	declare @pubid					uniqueidentifier			 
	declare @partnerid				uniqueidentifier			 
    declare @parentid               uniqueidentifier

	/*
    ** Initializations.
    */

    SET @nosync 			= 2       /* Const: synchronization type 'nosync' */
    SET @automatic 			= 1       /* Const: synchronization type 'automatic' */
	SET @inactive 			= 0
    SET @global 			= 1
	SET @push 				= 0   


	set @pubid 				= newid()
	set @partnerid			= @pubid
	
	set @parentid			= '00000000-0000-0000-0000-000000000000'
	 
	/* 
	** Check if replication components are installed on this server
	*/
	exec @retcode = dbo.sp_MS_replication_installed
	if (@retcode <> 1)
	begin
		return (1)
	end

    /*
    ** Security Check.
    */

	EXEC @retcode = dbo.sp_MSreplcheck_subscribe
	if @@ERROR <> 0 or @retcode <> 0
		return(1)

	/*
	**	Check to see if merge system tables exist. Create them unless they already
	**  exist.
	*/
	IF not exists (select name from sysobjects where name='sysmergesubscriptions')
		BEGIN
			execute @retcode = dbo.sp_MScreate_mergesystables
				if @@ERROR <> 0 or @retcode <> 0
					begin
						return (1)
					end
		END	

	if UPPER(@publisher) = UPPER(@@SERVERNAME) and @publisher_db = db_name()
		begin
			raiserror(21126, 16, -1)
			return (1)
		end

	if exists (select pubid from sysmergepublications where UPPER(publisher) = UPPER(@@SERVERNAME) and publisher_db=db_name()) and @subscriber_type in ('local', 'anonymous')
		begin
            declare @dbname sysname
            select @dbname = DB_NAME()
    	    raiserror(21127, 16, -1, @dbname)
			return (1)
		end
	/* 
	** When adding a pull subscription, if a push subscription for that publication already exists, 
	** we will cleanup all the traces of that subscription
	*/
	IF EXISTS (select name from sysmergepublications where name = @publication and UPPER(publisher)=UPPER(@publisher) and publisher_db=@publisher_db)
	BEGIN
		select @pubid=pubid from sysmergepublications 
			where name = @publication and UPPER(publisher)=UPPER(@publisher) and publisher_db=@publisher_db
		IF EXISTS (select subid from sysmergesubscriptions where pubid=@pubid and subid<>@pubid and subscription_type=0)
			begin
				exec @retcode = dbo.sp_MSpublicationcleanup @publisher=@publisher,
														@publisher_db=@publisher_db,
														@publication=@publication
				IF @@ERROR <> 0 or @retcode <>0
		    		BEGIN
					RAISERROR (20025, 16, -1, @publication)
					return (1)
					END	
			end
		ELSE
			begin
				IF EXISTS (select status from sysmergesubscriptions where pubid=@pubid and status =	2)
					begin
						select @subid = subid from sysmergesubscriptions where pubid=@pubid and subid<>pubid
						delete sysmergesubscriptions where pubid=@pubid
						delete MSmerge_replinfo where repid = @subid
					end
				ELSE 
					begin
						RAISERROR (14058, 16, -1)
						return (1)
					end
			end
	END
	
	set @partnerid = @pubid
     
  	/*
    ** Assign parameter values appropriately for the local server database
	*/
	set @subscriber_db = DB_NAME()
	select @subscriber_srvid = 0

    /*
    ** Parameter Check: @publisher
    ** Check to make sure that the publisher is defined
    */
    IF @publisher IS NULL
    BEGIN
        RAISERROR (14043, 16, -1, '@publisher')
        RETURN (1)
    END

    IF @publisher = 'all'
    BEGIN
        RAISERROR (14136, 16, -1)
        RETURN (1)
    END

    EXECUTE @retcode = dbo.sp_validname @publisher
    IF @@ERROR <> 0 OR @retcode <> 0
       RETURN (1)
	/*
	** Validate that the publisher is a valid server
	*/
	select @publisher_srvid = srvid from master..sysservers where UPPER(srvname) = UPPER(@publisher)
    IF @publisher_srvid IS NULL
		BEGIN
		    EXECUTE @retcode = dbo.sp_addserver @publisher
	        IF @@error <> 0 OR @retcode <> 0
    			BEGIN
		    		RAISERROR (14010, 16, -1)
			       	RETURN (1)
	            END
	        ELSE
	        	select @publisher_srvid = srvid from master..sysservers where UPPER(srvname) = UPPER(@publisher)
		END


    /*
    ** Parameter Check: @publisher_db
    */
    IF @publisher_db IS NULL
    BEGIN
        RAISERROR (14043, 16, -1, '@publisher_db')
        RETURN (1)
    END

    IF @publisher_db = 'all'
    BEGIN
        RAISERROR (14136, 16, -1)
        RETURN (1)
    END
	
	/*
	** Check to see if the publication name is already used in the subscription 
	** database - This is the case where we are resubscribing to the same publication.
	** Execute dbo.sp_MSpublicationcleanup to cleanup all all the defunct rows
	
	** if exists (select * from sysmergepublications where name = @publication)
	** begin
	**	exec @retcode = dbo.sp_MSpublicationcleanup 
	**    IF @@ERROR <> 0 OR @retcode <> 0
	**    	BEGIN
	**			RAISERROR (20025, 16, -1, @publication)
	**	    	RETURN (1)
	**		END				    	
	** end
	*/

    /*
    ** Parameter Check: @subscriber_type.
    ** Set subscriber_typeid based on the @subscriber_type specified.
    **
    **   subscriber_type     subscriber_type
    **   =================    ===============
    **             1     		global
    **             2     		local
    **             3     		anonymous
    **             NO support for republisher for B 3
    */
    if LOWER(@subscriber_type) NOT IN ('local', 'global', 'anonymous')
        BEGIN
		  	RAISERROR (20023, 16, -1)
			RETURN (1)
        END

	set @subscription_type = 1 /* pull by default */
    if LOWER(@subscriber_type) IN ('global')
        set @subscriber_typeid = 1
    else if LOWER(@subscriber_type) IN ('local')
        set @subscriber_typeid = 2
	else if LOWER(@subscriber_type) IN ('anonymous')       
		begin
			/* For anonymous subscribers set subscription type appropriately */
	        set @subscriber_typeid = 3
	        set @subscription_type = 2
		end	        

	/* 
	** Assign priority appropriately - choose 0.99 times the minimum priority
	** of the global replicas.
	*/
	if (@subscription_priority > 100.0 or @subscription_priority < 0.0)
		set @subscription_priority = NULL		
	if (@subscription_priority IS NULL)
		begin
			select @priority = 0.99 * min(priority) from sysmergesubscriptions where subscriber_type  = 1 /* global/loopback */
			if (@priority IS NOT NULL)
				select @subscription_priority = @priority
			if (@subscription_priority IS NULL) 
				select @subscription_priority = 0.0
		end
	/*
	** For local and anonymous subscriptions the priority is 0.0
	*/
    if LOWER(@subscriber_type) IN ('local', 'anonymous')
		select @subscription_priority = 0.0

	/*
 	** If the subscription already exists, don't add it.
	
 	** if EXISTS (select db_name, srvid
 	**		FROM sysmergesubscriptions
    ** 		WHERE db_name = @subscriber_db
    ** 		AND srvid = @subscriber_srvid                	       
    **    	AND pubid = @pubid)
	**	BEGIN
	**		RAISERROR (14058, 16, -1)
	**		RETURN (1)
 	**	END
	*/

   /*
   ** Parameter Check: @sync_type.
   ** Set sync_typeid based on the @sync_type specified.
   **
   **   sync_typeid     sync_type
   **   ===========     =========
   **             1     automatic
   **             2     nosync
   */


   IF LOWER(@sync_type) NOT IN ('automatic', 'none')
       BEGIN
           RAISERROR (14052, 16, -1)
           RETURN (1)
       END


   IF LOWER(@sync_type) = 'automatic'
   BEGIN
		SET @sync_typeid = @automatic
   END
   ELSE
   BEGIN
        SET @sync_typeid = @nosync
   END


	/*
	** UNDONE: Validate that the publisher is of type 'republisher'
	*/

	begin tran
    save TRAN addmergepullsubscription
		
		/* Generate a guid for the Subscriber ID */
		set @subid = newid()

		/* Look for existing nickname from any other subscription */
		exec dbo.sp_MSgetreplnick NULL, NULL , NULL,  @subnickname out
		if (@@error <> 0) 
	        begin
            goto FAILURE
	        end                 


		/* Generate a new replica nickname from the @subid */
		if (@subnickname is null)
			EXECUTE dbo.sp_MSgenreplnickname @subid, @subnickname output

	
		/* 
		** Check to see if MSsubscription_properties table exists.
		** If not, create it.
		*/
		exec @retcode = dbo.sp_MScreate_sub_tables
		IF @@ERROR <> 0 or @retcode <> 0
			goto FAILURE

		/*
		** The subscription doesn't exist, so let's add it to sysmergesubscriptions 
		*/
		INSERT sysmergesubscriptions (subid, partnerid, datasource_type, srvid, db_name, 
				pubid, status, subscriber_type, subscription_type, priority, sync_type, description, login_name)
					VALUES (@subid,
							@partnerid,
							0,
		    				@subscriber_srvid,
		    				@subscriber_db,
		    				@pubid,
		    				@inactive,
		    				@subscriber_typeid,
							@subscription_type, 	/* for a pull/anon subscription */
		    				@subscription_priority,
		    				@sync_typeid,
		    				@description,
		    				suser_sname(suser_sid()))			
		if @@ERROR <> 0
			BEGIN
				GOTO FAILURE
			END

		/* Add a self-subscribed subscription to represent the publication */
			
		insert sysmergepublications(publisher, publisher_db, pubid, name, parentid) 
			values(@publisher, @publisher_db, @pubid, @publication, @parentid)
		if @@ERROR <> 0
			begin
				goto FAILURE
			end
		insert sysmergesubscriptions(subid, partnerid, datasource_type, srvid, db_name, 
				pubid, subscriber_type, subscription_type, status, priority, sync_type, description, login_name)
			values (@pubid, @pubid, 0, @publisher_srvid, @publisher_db, 
				@pubid, @global, @push, @inactive, 100.0, @sync_typeid, @description, suser_sname(suser_sid()))  
						
		if @@ERROR <> 0
			begin
				goto FAILURE
			end
					
		/*
		**  Add row for subscription in MSmerge_replinfo.
		*/
		insert MSmerge_replinfo(repid, replnickname)
				values (@subid, @subnickname)
		if @@ERROR <> 0
			BEGIN
				GOTO FAILURE
			END

    COMMIT TRAN
	return (0)

FAILURE:
	RAISERROR (14057, 16, -1)
	if @@trancount > 0
	begin
		ROLLBACK TRANSACTION addmergepullsubscription
		COMMIT TRANSACTION
	end
	RETURN (1)

go
exec dbo.sp_MS_marksystemobject sp_addmergepullsubscription 
go

grant execute on dbo.sp_addmergepullsubscription to public
go
 
raiserror('Creating procedure sp_changemergepullsubscription', 0,1)
GO

CREATE PROCEDURE sp_changemergepullsubscription (
	@publication 		sysname = '%',	/* Publication name */
	@publisher			sysname = '%',  /* Publisher server */
	@publisher_db		sysname = '%', 	/* Publication database */
    @property 			sysname = NULL, /* The property to change */
    @value 				nvarchar(255) = NULL	/* The new property value */
    ) AS

    SET NOCOUNT ON

    /*
    ** Declarations.
    */
    declare @subscriber_srvid	 	int
    declare @publisher_srvid	 	int
	declare @retcode 				int
	declare	@pubid 					uniqueidentifier
	declare	@subid 					uniqueidentifier
	declare	@partnerid 				uniqueidentifier
    declare @sync_typeid 			tinyint
    declare @nosync 				tinyint
    declare @automatic 				tinyint
     
    declare @artid					uniqueidentifier
	declare @subscriber				sysname
	declare @subscriber_db			sysname
    declare @schematype				int
	declare @schemaversion			int
	declare @schemaguid				uniqueidentifier
    declare @db_name				sysname
    declare @subscriber_type		int
    declare @schematext				nvarchar(2000)
     

    /*
    ** Initializations.
    */
    SET @subscriber 	= @@SERVERNAME
    SET @subscriber_db	= DB_NAME()
    SET @nosync 		= 2     /* Const: synchronization type 'none' */
    SET @automatic 		= 1     /* Const: synchronization type 'automatic' */

	select @subscriber_srvid = srvid from master..sysservers where UPPER(srvname) = UPPER(@subscriber)
    IF @subscriber_srvid IS NULL
		BEGIN
		   RAISERROR (14010, 16, -1)
		   RETURN (1)     
		END

    /*
    ** Security Check.
    */
	BEGIN
		exec @retcode = dbo.sp_MSreplcheck_subscribe
		if @@ERROR <> 0 or @retcode <> 0
			return(1)
	END


	/*
	**	Check to see if current database is enabled for subscribing
	*/
	IF not exists (select name from sysobjects where name='sysmergesubscriptions')
		BEGIN
        	RAISERROR (14055, 16, -1)
	    	RETURN (1)
		END

	
    /*
    ** Parameter Check:  @property.
    ** If the @property parameter is NULL, print the options.
    */

    IF @property IS NULL
        BEGIN
            CREATE TABLE #tab1 (properties sysname NOT NULL)
            INSERT INTO #tab1 VALUES ('sync_type')
            INSERT INTO #tab1 VALUES ('priority')
            INSERT INTO #tab1 VALUES ('description') 
            select * FROM #tab1
            RETURN (0)
        END

    /*
    ** Parameter Check:  @publisher.
    ** Check to make sure we have a valid publisher.
    ** Should make sure that @publisher is non-null before using it to check whether @publication is valid
    */
    IF @publisher IS NULL
        BEGIN
            RAISERROR (14043, 16, -1, '@publisher')
            RETURN (1)
        END

    /*
    ** Parameter Check:  @publication.
    ** Make sure that the publication exists.
    */

    IF @publication IS NULL
        BEGIN
            RAISERROR (14043, 16, -1, '@publication')
            RETURN (1)
        END

    select @pubid = pubid FROM sysmergepublications WHERE name = @publication and UPPER(publisher)=UPPER(@publisher) and publisher_db=@publisher_db
    IF @pubid IS NULL
        BEGIN
            RAISERROR (20026, 11, -1, @publication)
            RETURN (1)
        END

	/*
	** Validate that the publisher is a valid server
	*/
	select @publisher_srvid = srvid from master..sysservers where UPPER(srvname) = UPPER(@publisher)
    IF @publisher_srvid IS NULL
		BEGIN
			RAISERROR (14010, 16, -1)
		   	RETURN (1)
		END

    /*
    ** Check to see if you have a local / global subscription on this publication
    */
    set @subid = NULL
	select @subid = subs1.subid, 
    @pubid = pubs.pubid, /* identified from publication name */
	@subscriber_type=subs1.subscriber_type,
    	@partnerid = subs2.subid from
		sysmergesubscriptions 	subs1,
	  	sysmergesubscriptions 	subs2,
		sysmergepublications 	pubs
		where subs1.srvid = @subscriber_srvid
			and subs1.db_name = @subscriber_db
			and subs2.srvid = @publisher_srvid
			and subs2.db_name = @publisher_db
			and subs1.pubid = subs2.subid
			and subs2.pubid = pubs.pubid
			and pubs.name = @publication
			and UPPER(pubs.publisher)=UPPER(@publisher)
			and pubs.publisher_db = @publisher_db

	if @subid IS NULL 
     	begin
            RAISERROR (14050, 11, -1)
            RETURN(1)
		end     			

    /*
    ** Parameter Check:  @property.
    ** Check to make sure that @property is a valid property in
    ** sysarticles.
    */

	
    IF LOWER(@property) NOT IN ('sync_type', 'priority', 'description')
        BEGIN
            RAISERROR (14051, 16, -1)
            RETURN (1)
        END

    /*
    ** Change the property.
    */
    IF LOWER(@property) = 'sync_type'
        BEGIN

            /*
            ** Check to make sure that we have a valid sync_type.
            */

            IF LOWER(@value) NOT IN ('automatic', 'none')
                BEGIN
                    RAISERROR (14052, 16, -1)
                    RETURN (1)
                END

            /*
            ** Determine the integer value for the sync_type.
            */

	        IF LOWER(@value) = 'automatic'
		        SET @sync_typeid = @automatic
	        ELSE
		        SET @sync_typeid = @nosync

            /*
            ** Update the subscription with the new sync_type.
            */

            UPDATE sysmergesubscriptions
               	SET sync_type = @sync_typeid
             	WHERE subid = @subid
            IF @@ERROR <> 0
                BEGIN
                    RAISERROR (14053, 16, -1)
                    RETURN (1)
                END

        END
        
	IF LOWER(@property) = 'description'
        BEGIN
		UPDATE sysmergesubscriptions
               	SET description = @value
             	WHERE subid = @subid
            IF @@ERROR <> 0
                BEGIN
                    RAISERROR (14053, 16, -1) 
              
                    RETURN (1)
                END

        END
        
     
    IF LOWER(@property) = 'priority'
    BEGIN

	select @db_name = db_name from sysmergesubscriptions
        where (pubid=@pubid) and (subid=@pubid)
        IF @db_name <> db_name()
        BEGIN
        	RAISERROR (20047, 16, -1)
            RETURN (1)
        END

    /* Only the original publisher can change priority of a global subscriptions */

    	IF @subscriber_type<>1  
        BEGIN
            RAISERROR (20044, 16, -1)  /* Local subscriber does not have priority*/
            RETURN (1)
        END
        
     	select @schemaversion = schemaversion from sysmergeschemachange
		if (@schemaversion is NULL)
		set @schemaversion = 1
		else
			select @schemaversion = 1 + max(schemaversion) from sysmergeschemachange
			
		 
		set @schemaguid = newid()
		set @artid = newid()
		set @schematype = 8 /* change priority */
		select @schematext = 'exec dbo.sp_MSchange_priority '+ '''' + convert(nchar(36),@subid) + '''' + ',' + '''' + @value + '''' 
		 
	BEGIN TRANSACTION
        exec dbo.sp_MSchange_priority @subid,  @value
	 	exec dbo.sp_MSinsertschemachange @pubid, @artid, @schemaversion, @schemaguid, @schematype, @schematext
	COMMIT TRANSACTION
	
	END
	
    /*
    ** Return succeed.
    */

    RAISERROR (14054, 10, -1)
    RETURN (0)
go

exec dbo.sp_MS_marksystemobject sp_changemergepullsubscription 
go

grant execute on dbo.sp_changemergepullsubscription to public
go


raiserror('Creating procedure sp_helpmergepullsubscription', 0,1)
GO

CREATE PROCEDURE sp_helpmergepullsubscription(
	@publication 		sysname = '%',		/* Publication name */
	@publisher			sysname = '%',  	/* Publisher server */
	@publisher_db		sysname = '%',  	/* Publication database */
	@subscription_type	nvarchar(10) = 'pull'	/* Show only pull subscriptions */
	)AS
	
    SET NOCOUNT ON

    /*
    ** Declarations.
    */

    declare @retcode 			int
    declare @srvid	 			int
	declare	@pubid 				uniqueidentifier
	declare	@subid 				uniqueidentifier
	declare	@partnerid 			uniqueidentifier
    declare @cursor_open		int
	declare @subscriber			sysname
	declare @subscriber_db		sysname
    declare @subscription_set 	nvarchar(10)
	declare @publisher_local	sysname
	declare @publisher_db_local	sysname
	declare @publication_local	sysname
	declare @subscription_name 	nvarchar(1000)
	declare @regkey				nvarchar(1000)
	declare @syncmgr_keyexist				int
	declare @helpsubscriptioncursor_open	int
	

    /*
    ** Initializations.
    */
	set @cursor_open 			= 0					

	select @publisher_db = RTRIM(@publisher_db)
	select @publication = RTRIM(@publication)
	
	/*
	**	Calling sp_help* is all right whether current database is enabled for pub/sub or not
	*/

	IF not exists (select * from sysobjects where name='sysmergesubscriptions')
		RETURN (0)

	/* Security check */
	EXEC @retcode = dbo.sp_MSreplcheck_subscribe
	if @@ERROR <> 0 or @retcode <> 0
		return(1)

	set @subscriber = @@SERVERNAME	 
	set @subscriber_db = DB_NAME()
 
    /*
    ** Parameter Check: @publisher
    ** Check to make sure that the publisher is defined
    */
    IF @publisher <> '%' AND @publisher IS NOT NULL
    BEGIN
		EXECUTE @retcode = dbo.sp_validname @publisher

    	IF @@ERROR <> 0 OR @retcode <> 0
       		RETURN (1)
    END
 
    /*
    ** Parameter Check:  @publication.
    ** If the publication name is specified, check to make sure that it
    ** conforms to the rules for identifiers and that the publication
    ** actually exists.  Disallow NULL.
    */
    if @publication IS NULL
        BEGIN
            RAISERROR (14043, 16, -1, '@publication')
            RETURN (1)
        END

	/*
    ** Parameter Check: @subscription_type.
    ** Set subscription_typeid based on the @subscription_type specified.
    **
    **   subscription_type    subscription_type
    **   =================    ===============
    **             0     		push
    **             1     		pull
    **			  0,1			both
    */
    if LOWER(@subscription_type) NOT IN ('push', 'pull', 'both')
        BEGIN
		  	RAISERROR (14128, 16, -1)
			RETURN (1)
        END
    IF LOWER(@subscription_type) = 'both'
        set @subscription_set = '(0, 1)'
    else IF LOWER(@subscription_type) = 'push'
        set @subscription_set = '(0)'
    else 
        set @subscription_set = '(1,2)'   -- including pull subscription and pull/anonymous subscription

    /*
    ** Get subscriptions
    */
	
	create table #helpmergepullsubscription
				(
					publication				sysname		NOT NULL,
					publisher				sysname		NOT NULL,
					publisher_db			sysname		NOT NULL,
					subscriber				sysname		NOT NULL,
					subscriber_db		 	sysname		NOT NULL,
					status    				int     	NOT NULL,
					subscriber_type 		int		    NOT NULL,
					subscription_type 		int		    NOT NULL,
					priority				float(8)	NOT NULL,
					sync_type				tinyint		NOT NULL,
					description				nvarchar(255) NULL,
					merge_jobid				binary(16)	NULL,
					enabled_for_syncmgr		int			NULL			
				)

    IF @publisher IS NULL and @publisher_db IS NULL
	    BEGIN
	    	select @subid = subid from sysmergesubscriptions where subid = partnerid
	    	set @partnerid = @subid
			-- show the loopback subscription
		    insert into #helpmergepullsubscription 
				select pubs.name, servers2.srvname, subs2.db_name, servers1.srvname, subs1.db_name, 
					subs1.status, subs1.subscriber_type, subs1.subscription_type, subs1.priority, 
					subs1.sync_type, subs1.description, replinfo.merge_jobid, 0
		    	FROM  	sysmergesubscriptions 	subs1,
		    		  	sysmergesubscriptions 	subs2,
		    		  	MSmerge_replinfo	 	replinfo,
	        			master..sysservers 		servers1,
	        			master..sysservers 		servers2,
						sysmergepublications 	pubs
				where subs1.subid = @subid
					and subs2.subid = @partnerid
					and pubs.pubid = subs1.pubid
					and servers1.srvid = subs1.srvid
					and servers2.srvid = subs2.srvid
					and subs1.subid = subs1.partnerid 
					and replinfo.repid = subs1.subid 
	    	
	    END
	else
		begin
		/*
			exec ('declare #cursor cursor FOR select DISTINCT sub.subid, sub.partnerid ' +
	        	'FROM sysmergesubscriptions 	sub, ' +
	    	    'sysmergesubscriptions 		sub1, ' +
	            'master..sysservers 			ss, ' + 
	            'master..sysservers 			ss1, ' +
	            'sysmergepublications 		pub ' +
	         	'WHERE ss.srvname LIKE ''' + @subscriber +
					'''AND UPPER(ss1.srvname) like UPPER(''' + @publisher +
					''') AND sub1.srvid = ss1.srvid ' +
	           		'AND sub.srvid = ss.srvid ' +
	           		'AND pub.name LIKE ''' + @publication + 
	           		'''AND sub.pubid = pub.pubid ' +
	           		'AND sub.db_name LIKE ''' + @subscriber_db +
	           		'''AND sub1.db_name LIKE ''' + @publisher_db +
					'''AND sub1.pubid = pub.pubid ' +
					'AND sub.subscription_type IN ' + @subscription_set + ' FOR READ ONLY')
			-- UNDONE 'AND sub1.subid = sub.partnerid ' 
		*/

			declare #cursor cursor local FAST_FORWARD FOR select DISTINCT sub.subid, sub.partnerid 
	        	FROM sysmergesubscriptions 	sub,
	    	    sysmergesubscriptions 		sub1, 
	            master..sysservers 			ss,  
	            master..sysservers 			ss1, 
	            sysmergepublications 		pub 
	         	WHERE ((@subscriber = N'%') OR (UPPER(ss.srvname) = UPPER(@subscriber))) 
					AND ((@publisher = N'%') OR (UPPER(ss1.srvname) = UPPER(@publisher))) 
					AND sub1.srvid = ss1.srvid 
	           		AND sub.srvid = ss.srvid  
	           		AND pub.name LIKE  @publication  
	           		AND sub.pubid = pub.pubid 
	           		AND sub.db_name LIKE  @subscriber_db 
	           		AND sub1.db_name LIKE @publisher_db 
					AND sub1.pubid = pub.pubid 
					AND (sub.subscription_type=1 or sub.subscription_type=2) 
				FOR READ ONLY

			open #cursor
			select @cursor_open = 1					
			fetch next from #cursor into @subid, @partnerid
			while (@@fetch_status <> -1)
				begin
				    insert into #helpmergepullsubscription 
						select pubs.name, servers2.srvname, subs2.db_name, servers1.srvname, subs1.db_name, 
							subs1.status, subs1.subscriber_type, subs1.subscription_type, subs1.priority, 
							subs1.sync_type, subs1.description, replinfo.merge_jobid, 0
				    	FROM  	sysmergesubscriptions 	subs1,
				    		  	sysmergesubscriptions 	subs2,
				    		  	MSmerge_replinfo	 	replinfo,
			        			master..sysservers 		servers1,
			        			master..sysservers 		servers2,
								sysmergepublications 	pubs
						where subs1.subid = @subid
							and subs2.subid = @partnerid
							and pubs.pubid = subs1.pubid
							and servers1.srvid = subs1.srvid
							and servers2.srvid = subs2.srvid
							and @subid <> @partnerid -- do not show the loopback subscription
							and replinfo.repid = subs1.subid 
		
					if @@ERROR <> 0
						begin
							set @retcode = 1
							goto DONE
						end					
				fetch next from #cursor into @subid, @partnerid
			end
		end

	declare #helpsubscriptioncursor CURSOR LOCAL FAST_FORWARD FOR 
		select DISTINCT publisher, publisher_db, publication
       	FROM #helpmergepullsubscription
			FOR READ ONLY
	create table #syncmgr_keyexist (syncmgr_keyexist int)
	open #helpsubscriptioncursor
	select @helpsubscriptioncursor_open = 1					
	fetch next from #helpsubscriptioncursor into @publisher_local, @publisher_db_local, @publication_local
	while (@@fetch_status <> -1)
		begin
			set @subscription_name = @publisher_local + ':' + @publisher_db_local + ':' + @publication_local + ':' + @subscriber + ':' + @subscriber_db
			/* Replace back slash with forward slash so that the key name is a valid REGISTRY key name */
			set @subscription_name = REPLACE(@subscription_name,'\','/')
			set @regkey = 'SOFTWARE\Microsoft\MSSQLServer\Replication\Subscriptions\' + @subscription_name
			insert into #syncmgr_keyexist EXECUTE master.dbo.xp_regread 'HKEY_LOCAL_MACHINE', @regkey
			select @syncmgr_keyexist = syncmgr_keyexist from #syncmgr_keyexist
			update #helpmergepullsubscription set enabled_for_syncmgr = @syncmgr_keyexist 
				where UPPER(publisher) = UPPER(@publisher_local)
					and publisher_db = @publisher_db_local
					and publication = @publication_local
				
			fetch next from #helpsubscriptioncursor into @publisher_local, @publisher_db_local, @publication_local
		end

	select 'subscription_name'= publisher + ':' + publisher_db + ':' + publication, *
				from #helpmergepullsubscription 
			order by publisher, publisher_db, publication, subscriber, subscriber_db
    	 
	select @retcode = 0
DONE:
	if (@cursor_open = 1)
		begin
			close #cursor
			deallocate #cursor
		end			
	drop table #helpmergepullsubscription

	if (@helpsubscriptioncursor_open = 1)
		begin
			close #helpsubscriptioncursor
			deallocate #helpsubscriptioncursor
		end			
	drop table #syncmgr_keyexist	
	return @retcode	
go
exec dbo.sp_MS_marksystemobject sp_helpmergepullsubscription
go

grant execute on dbo.sp_helpmergepullsubscription to public
go

raiserror('Creating procedure sp_addmergepullsubscription_agent', 0,1)
GO
CREATE PROCEDURE sp_addmergepullsubscription_agent (
	@name							sysname = NULL,
	@publisher						sysname,  						/* Publisher server */
	@publisher_db					sysname,  						/* Publisher database */
	@publication 					sysname,	      				/* Publication name */
	@publisher_security_mode		int = 1,
	@publisher_login				sysname = NULL,
	@publisher_password				sysname = NULL,
	@publisher_encrypted_password	bit = 0,
	@subscriber						sysname = NULL,
	@subscriber_db					sysname = NULL,
	@subscriber_security_mode		int = NULL,						/* 0 standard; 1 integrated */
	@subscriber_login				sysname = NULL,
	@subscriber_password			sysname = NULL,
	@distributor					sysname = @@SERVERNAME,
	@distributor_security_mode		int = 1,						/* 0 standard; 1 integrated */
	@distributor_login				sysname = NULL,
	@distributor_password			sysname = NULL,
	@encrypted_password				bit = 0,			/* distributor password encrypted or not */
    @frequency_type  				int = NULL,
    @frequency_interval 			int = NULL,				
    @frequency_relative_interval 	int = NULL, 
    @frequency_recurrence_factor 	int = NULL, 
	@frequency_subday 				int = NULL,
    @frequency_subday_interval 		int = NULL,	   
    @active_start_time_of_day 		int = NULL, 
    @active_end_time_of_day 		int = NULL,         
    @active_start_date 				int = NULL, 
    @active_end_date 				int = NULL,
	@optional_command_line 			nvarchar(255) = '',			/* Optional command line arguments */
    @merge_jobid					binary(16) = NULL OUTPUT,
    @enabled_for_syncmgr nvarchar(5) = 'false', /* Enabled for SYNCMGR: true or false */
	@ftp_address sysname = NULL,
	@ftp_port int = NULL,
	@ftp_login sysname = NULL,
	@ftp_password sysname = NULL
    ) AS

    SET NOCOUNT ON

    /*
    ** Declarations.
    */
    declare @command 				nvarchar(4000)
    declare @retcode 				int
	declare @database				sysname
	declare @repid					uniqueidentifier
	declare @pubid					uniqueidentifier
    declare @subscriber_srvid		int 
    declare @publisher_srvid		int 
	declare @name_id				nvarchar(50)
	declare @subscriber_typeid		int
	declare @subscription_type_id	int
	declare @category_name			sysname
	declare @platform_nt			binary
	DECLARE @subscriber_enc_password sysname

	select @platform_nt = 0x1

	-- Set null @optional_command_line to empty string to avoid string concat problem
	if @optional_command_line is null
		set @optional_command_line = ''

	IF @distributor_password = N''
		select @distributor_password = [REDACTED]

	IF @publisher_password = N''
		select @publisher_password = [REDACTED]

	IF @ftp_password = N''
		select @ftp_password = [REDACTED]

	/*
	** Parameter Check: @subscriber and @subscriber_db
	*/

	if @subscriber IS NULL or rtrim(@subscriber) = ''
		SELECT @subscriber = @@SERVERNAME

	if @subscriber_db IS NULL or rtrim(@subscriber_db) = ''
		SELECT @subscriber_db = DB_NAME()
	
	EXECUTE @retcode = dbo.sp_validname @subscriber
    IF @@ERROR <> 0 OR @retcode <> 0
       RETURN (1)
	
    EXECUTE @retcode = dbo.sp_validname @subscriber_db
    IF @@ERROR <> 0 OR @retcode <> 0
       RETURN (1)

	-- Parameter check: @subscriber_security_mode	
	if @subscriber_security_mode is null
	begin
		if ( platform() & @platform_nt ) = @platform_nt
			select @subscriber_security_mode = 1
		else
			select @subscriber_security_mode = 0
	end	

	if ( ( platform() & @platform_nt ) <> @platform_nt and @subscriber_security_mode = 1)
	begin
		RAISERROR(21038, 16, -1)
		RETURN (1)
	end

	select @subscription_type_id = 1 /* pull agent only */
	/*
	** Set Default schedule values if NULL is specified
	** The default are not implemented during parmeter defintion because this procedure
	** is can be called from sp_addmergesubscription.
	*/
	if @frequency_type is NULL
		set @frequency_type = 4		/* Daily */
	if @frequency_interval is NULL
		set @frequency_interval = 1
	if @frequency_relative_interval is NULL
		set @frequency_relative_interval = 1
	if @frequency_recurrence_factor is NULL
		set @frequency_recurrence_factor = 0
	if @frequency_subday is NULL
		set @frequency_subday = 8	/* Hour */
    if @frequency_subday_interval is NULL
		set @frequency_subday_interval = 1
    if @active_start_time_of_day is NULL
		set @active_start_time_of_day = 0
    if @active_end_time_of_day is NULL
		set @active_end_time_of_day = 235959
    if @active_start_date is NULL
		set @active_start_date = 0
    if @active_end_date is NULL
		set @active_end_date = 99991231

	select @subscriber_srvid = srvid from master..sysservers where UPPER(srvname) = UPPER(@@SERVERNAME)
    IF @subscriber_srvid IS NULL
		BEGIN
		   RAISERROR (14010, 16, -1)
		   RETURN (1)     
		END
			
	select @pubid = pubid from sysmergepublications where name = @publication
		IF @pubid is NULL
			begin
				RAISERROR (14027, 16, -1, @publication)
				RETURN (1)
			end
			
	select @repid = subid, @subscriber_typeid = subscriber_type from sysmergesubscriptions
			where srvid = @subscriber_srvid and pubid<>subid and pubid = @pubid

	if @subscriber_typeid = 3 set @subscription_type_id = 2 /* This corresponds to anonymous subscription */

	if (@subscription_type_id <> 0)
	begin
		if (@subscriber_security_mode = 0) and (@subscriber_login IS NULL or rtrim(@subscriber_login) = '')
		begin
			raiserror(3217, 16, -1, '@subscriber_login')
			return (1)
		end
	end

	IF NOT EXISTS (select * from sysobjects where name = 'MSsubscription_properties' and type = 'U')
	begin
		raiserror(14027, 16, -1, 'The subscription properties table ''MSsubscription_properties''')
		return (1)
	end
	
	/*
    ** Construct unique task name if @name = NULL
	*/
	IF @name IS NULL
		begin
			 SELECT @name = CONVERT(nvarchar(23),@publisher ) + '-' + CONVERT(nvarchar(23),@publisher_db) + '-' + 
						CONVERT(nvarchar(23),@publication) + '-' + CONVERT(nvarchar(23),@subscriber) + '-' +
						CONVERT(nvarchar(23), @subscriber_db) + '- 0'
		end
	else
	begin
		/*
		** validate name
		*/
		exec @retcode = dbo.sp_MSreplcheck_name @name
		if @@ERROR <> 0 or @retcode <> 0
			return(1)

	end
	/* Construct task command */
	select @command = '-Publisher ' + @publisher + ' -PublisherDB ' + QUOTENAME(@publisher_db) + ' '
	select @command = @command + '-Publication ' + QUOTENAME(@publication) + ' '
	select @command = @command + '-Subscriber ' + QUOTENAME(@@SERVERNAME)  + ' '
	select @command = @command + '-SubscriberDB ' + QUOTENAME(db_name()) + ' '
	SELECT @command = @command + '-SubscriptionType ' + convert(nvarchar(10), @subscription_type_id)  + ' '
	
	select @command = @command + '-SubscriberSecurityMode ' + 
		convert(nvarchar(10),@subscriber_security_mode) + ' '
	if @subscriber_login is not NULL
		select @command = @command + '-SubscriberLogin ' + quotename(@subscriber_login) + ' '
	if @subscriber_password is not NULL
	begin
		set @subscriber_enc_password = [REDACTED]
		exec @retcode = master.dbo.xp_repl_encrypt @subscriber_enc_password OUTPUT
		select @command = @command + '-SubscriberEncryptedPassword ' + quotename(@subscriber_enc_password) + ' '
	end
	
	select @command = @command + @optional_command_line
	select @command = @command + '-Distributor ' + @distributor + ' '
	
	select @database = db_name()

	-- Get Merge category name (assumes category_id = 14)
	select @category_name = name FROM msdb.dbo.syscategories where category_id = 14

begin tran
	EXEC @retcode = dbo.sp_MSadd_repl_job
			@name = @name,
			@subsystem = 'Merge',
			@server = @@SERVERNAME,
			@databasename = @database,
			@enabled = 1,
			@freqtype = @frequency_type,
			@freqinterval = @frequency_interval,
			@freqsubtype = @frequency_subday,
			@freqsubinterval = @frequency_subday_interval,
			@freqrelativeinterval = @frequency_relative_interval,
			@freqrecurrencefactor = @frequency_recurrence_factor,
			@activestartdate = @active_start_date,
			@activeenddate = @active_end_date,
			@activestarttimeofday = @active_start_time_of_day,
			@activeendtimeofday = @active_end_time_of_day,
			@command = @command,
			@retryattempts = 10,
			@retrydelay = 1,
			@category_name = @category_name,
			@job_id = @merge_jobid OUTPUT

	if @@ERROR <> 0 or @retcode <> 0
		begin
			goto undo
		end

	if (@subscription_type_id = 1) OR (@subscription_type_id = 2)
	begin
		IF NOT EXISTS (select * from MSsubscription_properties 
            where UPPER(publisher) = UPPER(@publisher)
			and publisher_db =  @publisher_db
			and publication = @publication) 
		BEGIN
			
			IF (@encrypted_password = 0)
			-- Encrypt the password
			BEGIN
				EXEC @retcode = master.dbo.xp_repl_encrypt @distributor_password OUTPUT
				IF @@error <> 0 OR @retcode <> 0
					return 1
			END
	
			IF (@publisher_encrypted_password = 0)
			-- Encrypt the password
			BEGIN
				EXEC @retcode = master.dbo.xp_repl_encrypt @publisher_password OUTPUT
				IF @@error <> 0 OR @retcode <> 0
					return 1
			END
	
			INSERT INTO MSsubscription_properties 
			(publisher, publisher_db, publication, publication_type, 
			 publisher_login,publisher_password, publisher_security_mode, 
			 distributor, distributor_login, distributor_password, 
			 distributor_security_mode, ftp_address, ftp_port, ftp_login, 
			 ftp_password)
			values 
			(@publisher, @publisher_db, @publication, 2, @publisher_login, 
			 @publisher_password, @publisher_security_mode, @distributor, 
			 @distributor_login, @distributor_password, 
			 @distributor_security_mode, @ftp_address, @ftp_port, @ftp_login,
			 @ftp_password)
			IF @@ERROR <> 0 
			BEGIN
				IF @@TRANCOUNT = 1
					ROLLBACK TRAN
				ELSE
					COMMIT TRAN           
				RETURN(1)
			END
		END
	end

		
	/* Update merge joibd for this pull subscription */
	UPDATE MSmerge_replinfo set merge_jobid = @merge_jobid WHERE repid = @repid

	/* Conditional support for MobileSync */
    if LOWER(@enabled_for_syncmgr) = 'true'
    BEGIN
		/* Call sp_MSregistersubscription so that the subscription can be synchronized via MobileSync etc. */
		exec @retcode = dbo.sp_MSregistersubscription @replication_type = 2,
									@publisher = @publisher,
									@publisher_db = @publisher_db,
									@publication = @publication,
								    @subscriber = @subscriber,
								    @subscriber_db = @subscriber_db,
									@subscriber_security_mode = @subscriber_security_mode,
									@subscriber_login = @subscriber_login,
									@subscriber_password = [REDACTED]
									@distributor = @distributor,
								    @subscription_id = @repid,
									@subscription_type = @subscription_type_id

		IF @@ERROR <> 0 or @retcode <> 0
	    BEGIN
			goto undo
	    END
	END

commit tran
	RETURN (0)
undo:
	IF @@TRANCOUNT = 1
		ROLLBACK TRAN
	ELSE COMMIT TRAN
GO

exec dbo.sp_MS_marksystemobject sp_addmergepullsubscription_agent
go

raiserror('Creating procedure sp_MSget_mergepullsubsagent_owner', 0,1)
GO
CREATE PROCEDURE sp_MSget_mergepullsubsagent_owner(
	@publication 		sysname = NULL,	      		/* Publication name */
	@publisher			sysname = NULL,  			/* Publisher server */
	@publisher_db		sysname = NULL,  			/* Publication database */
    @owner_sid          varbinary(85) OUTPUT
	)AS
    
    declare @srvid  int
    declare @pubid  uniqueidentifier 
    declare @subid  uniqueidentifier
    declare @job_id uniqueidentifier
    set nocount on

    select @owner_sid = NULL

    if exists (select * from sysobjects 
               where type = 'U' and
                     name = 'sysmergesubscriptions')
        -- Get the server id of the current server (subscriber)
    begin
        -- Get the srvid of the current subscriber database 
        select @srvid = srvid 
        from master.dbo.sysservers      
        where upper(@@servername) = upper(srvname)

        -- Get the pubid from sysmergepublications using @publisher, 
        -- @publisher_db, @publication 
        select @pubid = pubid
        from sysmergepublications
        where @publication = name

        -- Get the subid from sysmergesubscriptions using @pubid and @srvid
        select @subid = subid
        from sysmergesubscriptions
        where @pubid = pubid and
              @srvid = srvid and
              pubid <> subid 

        -- Get the merge_jobid from MSreplication_info using @subid
        select @job_id = merge_jobid
        from MSmerge_replinfo
        where @subid = repid

        -- Finally, get the owner_sid from msdb..sysjobs using @job_id
        select @owner_sid = owner_sid
        from msdb..sysjobs 
        where @job_id = job_id
    end
go

exec dbo.sp_MS_marksystemobject 'sp_MSget_mergepullsubsagent_owner'

raiserror('Creating procedure sp_dropmergepullsubscription', 0,1)
GO
CREATE PROCEDURE sp_dropmergepullsubscription(
	@publication 		sysname = NULL,	      		/* Publication name */
	@publisher			sysname = NULL,  			/* Publisher server */
	@publisher_db		sysname = NULL,  			/* Publication database */
	@reserved			bit = 0
	)AS

    SET NOCOUNT ON

    /*
    ** Declarations.
    */

    declare @retcode 				int
    declare @subscriber_srvid	 	int
    declare @publisher_srvid	 	int
	declare	@pubid 					uniqueidentifier
	declare	@subid 					uniqueidentifier
	declare	@partnerid 				uniqueidentifier 
	declare @local_server			sysname
	declare @local_db				sysname
    declare @merge_jobid 			binary(16)
    declare @cmd 					nvarchar(255)
    declare @pubidstr				nvarchar(38)
	declare @subscriber				sysname
	declare @subscriber_db			sysname
	declare @subscriber_type		int
	declare @local_job 				bit
	declare @implicit_transaction	int
	declare @close_cursor_at_commit int
    declare @owner_sid              varbinary(85)
    declare @owner_name             sysname
    declare @qualified_publication_name nvarchar(512)


	select @close_cursor_at_commit = 0
	select @implicit_transaction = 0

	/*
	** Get original setting values before setting them to false for recursive calling
	*/
	IF (@reserved = 0)
	BEGIN
		SELECT @implicit_transaction = @@options & 2
		SELECT @close_cursor_at_commit = @@options & 4
		SET IMPLICIT_TRANSACTIONS OFF
		SET CURSOR_CLOSE_ON_COMMIT OFF
	END

    /* 
	** Security Check.
    */
	exec @retcode = dbo.sp_MSreplcheck_subscribe
	if @@ERROR <> 0 or @retcode <> 0
		return(1)

     /*
    ** Initializations.
    */				
	set @local_db = DB_NAME()
	set @local_server = @@SERVERNAME
	set @subscriber = @@SERVERNAME	 
	set @subscriber_db = DB_NAME()

   /*
	** Assign parameter values appropriately
    */
		    
	select @subscriber_srvid = srvid from master..sysservers where UPPER(srvname) = UPPER(@subscriber)
	IF @subscriber_srvid IS NULL
		BEGIN
		   RAISERROR (14010, 16, -1)
		   RETURN (1)     
		END
		
	IF not exists (select name from sysobjects where name='sysmergesubscriptions')
		BEGIN
        	RAISERROR (14055, 16, -1)
	    	RETURN (1)
		END		

	/*
	** Parameter Check: @publisher
	** Check to make sure that the publisher is defined
	*/
		    IF @publisher IS NULL
		    BEGIN
		        RAISERROR (14043, 16, -1, '@publisher')
		        RETURN (1)
		    END

		    EXECUTE @retcode = dbo.sp_validname @publisher
		    IF @@ERROR <> 0 OR @retcode <> 0
		       RETURN (1)

	/*
	** Parameter Check: @publisher_db
	*/
		    IF @publisher_db IS NULL
		    BEGIN
		        RAISERROR (14043, 16, -1, '@publisher_db')
		        RETURN (1)
		    END    

    /*
    ** Parameter Check:  @publication.
    ** If the publication name is specified, check to make sure that it
    ** conforms to the rules for identifiers and that the publication
    ** actually exists.  Disallow NULL.
    */
    if @publication IS NULL
        BEGIN
            RAISERROR (14043, 16, -1, '@publication')
            RETURN (1)
        END

    IF LOWER(@publication) = 'all'
        BEGIN
        	declare hC1 CURSOR LOCAL FAST_FORWARD FOR select DISTINCT name FROM sysmergepublications FOR READ ONLY
            
            OPEN hC1
            FETCH hC1 INTO @publication
            if @@fetch_status = -1 
            	begin
					CLOSE hC1
            		DEALLOCATE hC1
            		RETURN (0) --- It's OK to have no publication when 'ALL'
				end
            WHILE (@@fetch_status <> -1)
                BEGIN
                    EXECUTE dbo.sp_dropmergepullsubscription @publication = @publication,
                                      @publisher = @publisher,
                                      @publisher_db = @publisher_db,
                                      @reserved = 1
                    FETCH hC1 INTO @publication
                END
            CLOSE hC1
            DEALLOCATE hC1
            RETURN (0)
        END
        
    IF LOWER(@publisher) = 'all'
        BEGIN
        	declare hC4 CURSOR LOCAL FAST_FORWARD FOR select DISTINCT srvname FROM master..sysservers FOR READ ONLY
            
            OPEN hC4
            FETCH hC4 INTO @publisher
            WHILE (@@fetch_status <> -1)
                BEGIN
                    EXECUTE dbo.sp_dropmergepullsubscription @publication = @publication,
                                                @publisher = @publisher,
                                                @publisher_db = @publisher_db,
                                                @reserved = 1
                    FETCH hC4 INTO @publisher
                END
            CLOSE hC4
            DEALLOCATE hC4
            RETURN (0)
        END

	/*
	** Validate that the publisher is a valid server
	*/
	select @publisher_srvid = srvid from master..sysservers where UPPER(srvname) = UPPER(@publisher)
    IF @publisher_srvid IS NULL
		BEGIN
			--RAISERROR (14010, 16, -1)
		   	RETURN (1)
		END


	/* Previously the condition is set as 'AND subid<>pubid' which is fatally errorous */

    IF LOWER(@publisher_db) = 'all'
        BEGIN
        	declare hC5 CURSOR LOCAL FAST_FORWARD FOR select DISTINCT db_name FROM sysmergesubscriptions 
        			WHERE subid = pubid and pubid in (select pubid from sysmergepublications 
        					where UPPER(publisher)=UPPER(@publisher) 
        						and name=@publication)
        						
        				FOR READ ONLY
            
            OPEN hC5
            FETCH hC5 INTO @publisher_db
            WHILE (@@fetch_status <> -1)
                BEGIN
                    EXECUTE dbo.sp_dropmergepullsubscription @publication = @publication,
                                      @publisher = @publisher,
                                      @publisher_db = @publisher_db,
                                      @reserved = 1
                    FETCH hC5 INTO @publisher_db
                END
            CLOSE hC5
            DEALLOCATE hC5
            RETURN (0)
        END

	/*
	** return error if only there is no 'ALL'. Same is true for the rest of error handling.
	*/
    if NOT EXISTS (select * FROM sysmergepublications 
    WHERE name = @publication and UPPER(publisher)=UPPER(@publisher) and publisher_db=@publisher_db) 
    BEGIN
		if @reserved = 0
			RAISERROR (20026, 16, -1, @publication)
        RETURN (1)
    END
        
	select @pubid = pubid from sysmergepublications where name = @publication and UPPER(publisher)=UPPER(@publisher) and publisher_db=@publisher_db
	set @pubidstr = '''' + convert(nchar(36), @pubid) + ''''
	if @pubid is null  
        BEGIN
			if @reserved = 0
				RAISERROR (20026, 16, -1, @publication)
           	RETURN (1)
        END

	/*
    ** Only members of the sysadmin group and the creator of the distribution
    ** agent can drop a pull subscription successfully. This behavior matches 
    ** the behavior of the sysjobs_view. DBO of the subscriber database, 
    ** sysadmins (owner is undefined) can drop a subscription if the owner_sid 
    ** is null.
    */
    
    EXEC sp_MSget_mergepullsubsagent_owner @publisher = @publisher,
                                           @publisher_db = @publisher_db,
                                           @publication = @publication,
                                           @owner_sid = @owner_sid OUTPUT 
    
    IF (@owner_sid is not null AND
        (SUSER_SID() <> @owner_sid) AND
        (ISNULL(IS_SRVROLEMEMBER('sysadmin'),0) = 0))
    BEGIN
        SELECT @owner_name = SUSER_SNAME(@owner_sid)
        SELECT @qualified_publication_name = @publisher + N':' + 
                                             @publisher_db + N':' +
                                             @publication
        RAISERROR(21121,16,-1,@owner_name, @qualified_publication_name) 
        RETURN (1)
    END

    /*
    ** Get subscriptions from either local replicas or global replicas
    */
	select @subid = subs1.subid, @subscriber_type = subs1.subscriber_type, @partnerid = subs2.subid from
		sysmergesubscriptions 	subs1,
	  	sysmergesubscriptions 	subs2,
		sysmergepublications 		pubs
		where subs1.srvid = @subscriber_srvid
			and subs1.db_name = @subscriber_db
			and subs2.srvid = @publisher_srvid
			and subs2.db_name = @publisher_db
			and subs1.pubid = subs2.subid
			and subs2.pubid = pubs.pubid
			and pubs.name = @publication
			and UPPER(pubs.publisher)=UPPER(@publisher)
			and pubs.publisher_db=@publisher_db

	if @subid IS NULL 
     	begin
			if @reserved = 0 
				raiserror (14050, 16, -1)
     		RETURN (0)
		end     			

	begin tran
    save TRAN dropmergepullsubscription
    
		/* 	
		** Drop the local merge task
		*/
		select @merge_jobid = merge_jobid from MSmerge_replinfo WHERE repid = @subid
		if (@merge_jobid IS NOT NULL)
		BEGIN
			IF EXISTS (SELECT * FROM msdb..sysjobs_view WHERE job_id = @merge_jobid)
			BEGIN
				EXEC @retcode = msdb.dbo.sp_delete_job @job_id = @merge_jobid
				IF @@ERROR <> 0 or @retcode <> 0
					GOTO FAILURE
			END
		END			    					

		if @subid <> @partnerid
		BEGIN
			IF (@subscriber_type<>1)
				begin
					DELETE MSmerge_replinfo WHERE repid = @subid 
					IF @@ERROR <> 0
						GOTO FAILURE
    				delete from sysmergesubscriptions where subid = @subid
					if @@ERROR <> 0
						GOTO FAILURE
				end
			ELSE
				update sysmergesubscriptions set status = 2 where subid =@subid

			/* Call sp_MSunregistersubscription so that the reg entries get deleted */
			exec @retcode = dbo.sp_MSunregistersubscription @publisher = @publisher,
										@publisher_db = @publisher_db,
										@publication = @publication,
										@subscriber = @@SERVERNAME,
										@subscriber_db = @subscriber_db
			IF @retcode<>0 or @@ERROR<>0
				GOTO FAILURE

			exec dbo.sp_MSpublicationcleanup @publisher=@publisher, 
											@publisher_db = @publisher_db,
											@publication = @publication
			IF @@ERROR <> 0 
		    	BEGIN
					RAISERROR (20025, 16, -1, @publication)
					GOTO FAILURE
				END
    	END
    	
    	IF EXISTS(select * from sysobjects where type='U' and name = 'MSsubscription_properties')
		BEGIN
			DELETE FROM MSsubscription_properties 
			WHERE UPPER(publisher) = UPPER(@publisher)	AND
			publisher_db  = @publisher_db AND
			publication = @publication 
	
			IF @@ERROR <> 0 
				GOTO FAILURE
	
			IF NOT EXISTS (SELECT * FROM MSsubscription_properties)
			BEGIN
				DROP TABLE MSsubscription_properties
				IF @@ERROR <> 0 
					GOTO FAILURE
			END
		END

		/* 
		** If last subscription is dropped and the DB is not enabled for publishing,
		** then remove the merge system tables
		*/
		IF (not exists (select * from sysmergesubscriptions )) 
			AND (select category & 4 FROM master..sysdatabases WHERE name = DB_NAME())=0
		BEGIN
				execute @retcode = dbo.sp_MSdrop_mergesystables
				if @@ERROR <> 0 or @retcode <> 0
					begin
						return (1)
					end
		END	
    COMMIT TRAN
	/*
	** Set back original settings
	*/
    IF @reserved = 0
	BEGIN
		IF @implicit_transaction <>0 
			SET IMPLICIT_TRANSACTIONS ON
		IF @close_cursor_at_commit <>0 
			SET CURSOR_CLOSE_ON_COMMIT ON
	END

	RETURN(0)    	

FAILURE:
	RAISERROR (14056, 16, -1)
	if @@trancount > 0
	begin
		ROLLBACK TRANSACTION dropmergepullsubscription
		COMMIT TRANSACTION
	end
	/*
	** Set back original settings
	*/	
	IF @reserved = 0
	BEGIN
		IF @implicit_transaction <>0 
			SET IMPLICIT_TRANSACTIONS ON
		IF @close_cursor_at_commit <>0 
			SET CURSOR_CLOSE_ON_COMMIT ON
	END
	return 1
go
exec dbo.sp_MS_marksystemobject sp_dropmergepullsubscription
go

grant execute on dbo.sp_dropmergepullsubscription to public
go

-- synctran supporting sprocs
raiserror('Creating procedure sp_MSreplraiserror', 0,1)
go

create proc sp_MSreplraiserror @errorid int, @param1 sysname = null, @param2 sysname= null
as
    if @errorid = 20508 raiserror (20508, 16, 1)
    else if @errorid = 20509 raiserror (20509, 16, 1)
    else if @errorid = 20510 raiserror (20510, 16, 1)
    else if @errorid = 20511 raiserror (20511, 16, 1)
    else if @errorid = 20512 raiserror (20512, 16, 1)
    else if @errorid = 20515 raiserror (20515, 16, 1)
    else if @errorid = 20516 raiserror (20516, 16, 1)
    else if @errorid = 20517 raiserror (20517, 16, 1)
    else if @errorid = 20518 raiserror (20518, 16, 1)
    else if @errorid = 20519 raiserror (20519, 16, 1)
    else if @errorid = 20520 raiserror (20520, 16, 1)
    else if @errorid = 21034 raiserror (21034, 16, 1)
    else if @errorid = 21054 raiserror (21054, 16, 1)
go

raiserror('Creating procedure sp_check_sync_trigger', 0,1)
go

create proc sp_check_sync_trigger @trigger_procid int, @trigger_op char(10) OUTPUT
as

    select @trigger_op = NULL

-- debug
--    select 'Entered sp_check_synctrigger', 'calling trigger' = object_name(@trigger_procid)
-- debug

	declare @trigid int

	select @trigid = so1.id from sysobjects so1, sysobjects so2 where
	so1.type = N'TR' and so1.name like N'trg_MSsync_ins_%' and so1.parent_obj = so2.parent_obj
	and so2.id = @trigger_procid
	
    -- if nestlevel of insert trigger on same table > 0 then bail

    if trigger_nestlevel( @trigid ) > 0
    begin
-- debug
--        select 'sp_check_synctrigger: synctran insert trigger is active, so do nothing'
-- debug
         return 1
    end
    else
        return 0
go

raiserror('Creating procedure sp_check_for_sync_trigger', 0,1)
go

create proc sp_check_for_sync_trigger @tabid int, @trigger_op char(10) = NULL OUTPUT
as

    select @trigger_op = NULL

-- debug
--    select 'Entered sp_check_for_sync_trigger', 'calling trigger' = object_name(@trigger_procid)
-- debug

    declare @ins_trigid int
	declare @upd_trigid int
	declare @del_trigid int

	select @ins_trigid = id from sysobjects where
	    type = N'TR' and name like N'trg_MSsync_ins_%' and parent_obj = @tabid
	select @upd_trigid = id from sysobjects where
	    type = N'TR' and name like N'trg_MSsync_upd_%' and parent_obj = @tabid
	select @del_trigid = id from sysobjects where
	    type = N'TR' and name like N'trg_MSsync_del_%' and parent_obj = @tabid

    if trigger_nestlevel( @ins_trigid ) > 0
    begin
-- debug
--     select 'sp_check_for_sync_trigger: synctran insert trigger is active'
-- debug
         select @trigger_op = 'ins'
         return 1
    end
    else    -- if nestlevel of insert trigger on same table > 0 then bail
    if trigger_nestlevel( @upd_trigid ) > 0
    begin
-- debug
--     select 'sp_check_for_sync_trigger: synctran update trigger is active'
-- debug
         select @trigger_op = 'upd'
         return 1
    end
    else
    if trigger_nestlevel( @del_trigid ) > 0
    begin
-- debug
--     select 'sp_check_for_sync_trigger: synctran update trigger is active'
-- debug
         select @trigger_op = 'del'
         return 1
    end
    else
        return 0
go

raiserror('Creating procedure sp_MSpad_command', 0,1)
go
create proc sp_MSpad_command
    @cmd     nvarchar(4000) output,
	@indent  int = 0  -- indent for command buffer (for pretty formatting
as
    declare @cnt int

    select @cmd = N''
    select @cnt = 0

	while (@cnt < @indent)
	begin
	    select @cmd = @cmd + N' '
		select @cnt = @cnt + 1
	end
go

raiserror('Creating procedure sp_MSflush_command', 0,1)
go
create proc sp_MSflush_command
    @cmd     nvarchar(4000) output,
	@force   int,     -- 0 = flush if necesssary, 1 = flush always
	@indent  int = 0  -- indent for command buffer (for pretty formatting
as
-- debug
--    if len(@cmd) >= 4000
--	begin
--	    raiserror("buffer overflow!", 16, 1)
--		select @cmd
--	end
-- debug

    if @force = 1 or len( @cmd ) > 3000
	begin
        insert into #proctext(procedure_text) values( @cmd )
        select @cmd = N''
		if @indent > 0 
		    exec dbo.sp_MSpad_command @cmd output, @indent
    end
go



raiserror('Creating procedure sp_MSget_colinfo', 0,1)
go
create proc sp_MSget_colinfo 
    @objid int,
    @colid int, 
	@columns binary(32), 
	@bGetTextImageInfo tinyint = 0, -- boolean for returning text/image info
	@colname sysname output, 
	@ccoltype sysname output
as
	declare @isset        int

    if @columns is not NULL
	    -- this code path for synctran procs
	    exec @isset = dbo.sp_isarticlecolbitset @colid, @columns
	else
	    -- this code path for synctran triggers
		select @isset = 1

    if @isset != 0 
    begin
	    select @colname = c.name, @ccoltype= t.name from syscolumns c, systypes t
	    where id = @objid and colid = @colid and c.xtype = t.xusertype
		-- when checking replicated columns, text/image datatypes cannot be declared or used locally
	    if (@bGetTextImageInfo = 0) and (@ccoltype in (N'text',N'ntext',N'image'))
		    return 1
	end
	else
	begin
        select @colname = null, @ccoltype = null
		return 1
	end

	return 0
go

raiserror('Creating procedure sp_MSget_col_position ', 0,1)
go
create procedure sp_MSget_col_position 
    @objid int,
	@columns binary(32),
	@key     sysname, 
	@colpos  sysname output,
	@art_col int = NULL output,
	@get_num_col bit = 0,
	@num_col  int = NULL output,
	@this_col int = null output
as
  
	declare @colname      sysname
	declare @ccoltype     sysname
	declare @src_cols     int
	declare @rc           int
	
	select @src_cols = count(*) from syscolumns where id = @objid
	select @this_col = 1

	select @num_col = 0

	
    while @this_col <= @src_cols 
    begin
		exec @rc = dbo.sp_MSget_colinfo @objid, @this_col, @columns, 0, @colname output, @ccoltype output
		if @rc = 0
	    begin
			set @num_col = @num_col + 1
			-- If @get_num_col is 1, we just need the number of columns in the partition.
			if @get_num_col = 0 and @colname = @key
			begin
			    select @colpos = 'c' + convert(varchar(4), @this_col)
				set @art_col = @num_col
				break
			end
		end
		set @this_col = @this_col + 1
    end
	return 0
go

raiserror('Creating procedure sp_MSget_type', 0,1)
go
create proc sp_MSget_type 
    @tabid int, 
	@colid int, 
	@colname sysname output, 
	@typestring nvarchar(4000) output
as
    declare @ccolchar       nvarchar(5)
    declare @coltype        tinyint
    declare @prec           smallint
    declare @scale          int
    declare @ccoltype       sysname
	declare @xtype          int

    select @colname = c.name, @xtype = c.xtype, @prec = c.prec, @scale = c.scale,
	    @ccoltype = t.name
    from syscolumns c, systypes t
    where c.id = @tabid and c.colid = @colid and 
	    c.xtype = t.xusertype
	 
	select @typestring = @ccoltype

	-- datatypes requiring precision (nchar, nvarchar, binary, varbinary)
	-- format: @var <dt> (prec)
	if @ccoltype in (N'char',N'nchar', N'varchar', N'nvarchar', N'binary', N'varbinary') 
	    select @typestring = @typestring + N'(' + rtrim(convert(nchar(10),@prec)) + N')'

	-- datatypes requiring precision & scale (numeric & decimal)
	-- format: @var <dt> (prec, scale)
	else if @ccoltype in (N'numeric', N'decimal') 
	    select @typestring = @typestring + N'(' + rtrim(convert(nchar(10),ColumnProperty(@tabid, @colname, 'PRECISION'))) + N',' + 
		    rtrim(convert(nchar(10),@scale)) + N')'
	
	-- text/image datatypes cannot be declared or used locally
	else if @ccoltype in (N'text',N'ntext',N'image')
	    select  @typestring = NULL
go

raiserror('Creating procedure sp_MSscript_where_clause', 0,1)
go
create procedure sp_MSscript_where_clause
    @objid		  int,
    @columns      binary(32), 
    @clause_type  varchar(6) = 'pk_new', -- 'new pk', 'old pk', 'upd ts', 'upd rc', 'trg pk'
    @ts_col       sysname = NULL,
    @indent       int = 0,
	@op_type      char(3) = NULL -- 'ins', 'del'
as
    declare @cmd          nvarchar(4000)
    declare @colname      sysname
    declare @ccoltype     sysname
    declare @spacer       nvarchar(20)
    declare @indkey       int
    declare @indid        int
    declare @key          sysname
    declare @rc           int
    declare @this_col     int
    declare @art_col      int
    declare @src_cols     int
    declare @col          sysname
	declare @qualname     nvarchar(512)

    select @spacer = N' ', @cmd = N''
    select @indkey = 1, @indid = 0
    exec sp_MSget_qualified_name @objid, @qualname OUTPUT
    select @src_cols = count(*) from syscolumns where id = @objid
    exec dbo.sp_MSpad_command @cmd output, @indent
    select @cmd = @cmd + N'where'
    exec dbo.sp_MSflush_command @cmd output, 1, @indent

    if @clause_type in ('new pk', 'old pk', 'upd ts', 'trg pk')
    begin
        exec @indid = dbo.sp_MStable_has_unique_index @objid

        if @indid > 0
	    begin
            while @indkey < 16 and index_col(@qualname, @indid, @indkey) is not null
            begin
                select @key = index_col(@qualname, @indid, @indkey)
                exec dbo.sp_MSget_col_position @objid, @columns, @key, @col output, 
					@this_col output
		
                if @clause_type = 'new pk'
                begin
                    if ColumnProperty(@objid, @key, 'IsIdentity') = 1
                        select @cmd = @cmd + @spacer + @key + N' = @@identity'
                    else
                        select @cmd = @cmd + @spacer + @key + N' = @' + @col

                    select @spacer = ' and
         '
                end
                else if @clause_type = 'upd ts'
                begin
                    select @cmd = @cmd + @spacer + @key + N' = @' + @col + N'_old'
                    select @spacer = ' and
         '
                end
                else if @clause_type in ('trg pk', 'old pk')
                begin
					if @op_type = 'ins'
						select @cmd = @cmd + @spacer + @key + N' = @' + @col + N'_old'
					else
						-- The vars correspoding to pk were set in sp_MSscript
						-- _pkvar_assignment.
						select @cmd = @cmd + @spacer + @key + N' = @' + @col 

                    select @spacer = ' and
         '
                end

                select @indkey = @indkey + 1
				
                -- flush command if necessary
                exec dbo.sp_MSflush_command @cmd output, 0, @indent
            end
	    end

        -- if clause_type is 'upd ts', add timestamp col
        if @clause_type = 'upd ts'
        begin
            exec dbo.sp_MSget_col_position @objid, @columns, @ts_col, @col output
            select @cmd = @cmd + @spacer + @ts_col + N' = @' + @col + N'_old'
        end

        -- save off command fragment
        exec dbo.sp_MSflush_command @cmd output, 1, @indent
    end
    else if @clause_type = 'upd rc'
    begin
        select @this_col = 1, @art_col = 1

        while @this_col <= @src_cols
        begin
            exec @rc = dbo.sp_MSget_colinfo @objid, @this_col, @columns, 0, @colname output, @ccoltype output
	    	if @rc = 0
            begin
                select @cmd = @cmd +  @spacer + '(' + @colname + N' = @c' + convert(varchar(4), @this_col) + N'_old or (' 
                select @cmd = @cmd + @colname + ' is null and @c' + convert(varchar(4), @this_col) + N'_old is null)) '
                select @spacer = N' and 
     '
                exec dbo.sp_MSflush_command @cmd output, 0, @indent
            end

            exec dbo.sp_MSflush_command @cmd output, 1, @indent

            select @this_col = @this_col + 1
        end

        -- save off cmd fragment
        exec dbo.sp_MSflush_command @cmd output, 1, @indent
    end
go

raiserror('Creating procedure sp_MSscript_params', 0,1)
go
create procedure sp_MSscript_params
    @objid   int,
	@columns binary(32),
	@postfix nvarchar(8) = NULL,
	@bOutParams tinyint = 0, -- boolean indicating wether or not to declare timestamp/identity params as output params
	@outvars nvarchar(4000) = NULL output
as
    declare @cmd          nvarchar(4000)
	declare @colname      sysname
	declare @typestring   nvarchar(4000)
	declare @spacer       nvarchar(1)
	declare @spacer2      nvarchar(1)
	declare @src_cols     int
	declare @this_col     int
	declare @art_col      int
	declare @isset        int

    select @spacer = N' '		
	select @spacer2 = N' '
	select @this_col = 1
	select @art_col = 1
	select @src_cols = count(*) from syscolumns where id = @objid
	select @outvars = null
	select @cmd = N''

    while @this_col <= @src_cols
    begin
	    if @columns is not null
            exec @isset = dbo.sp_isarticlecolbitset @this_col, @columns
		else
		    select @isset = 1

        if @isset != 0 and EXISTS (select name from syscolumns where id=@objid and colid=@this_col and iscomputed<>1) 
        begin
            exec dbo.sp_MSget_type @objid, @this_col, @colname output, @typestring OUTPUT
            if @typestring != NULL
			begin
				if @postfix is null
				    select @cmd = @cmd + @spacer + N'@c' + convert(varchar(4), @this_col) + N' ' + @typestring 
                else
				    -- old vars
				    select @cmd = @cmd + @spacer + N'@c' + convert(varchar(4), @this_col) + @postfix + N' ' + @typestring

                -- new vars of type timestamp and identity are declared as output params
                if @bOutParams = 1 and (@typestring = N'timestamp' or ColumnProperty(@objid, @colname, 'IsIdentity') = 1)
				begin
				    select @cmd = @cmd + N' output'
				    select @outvars = isnull(@outvars, N'') + @spacer2 + N'@c' + convert(varchar(4), @this_col) + N' = ' + @colname 
					select @spacer2 = N','
				end
				
				select @spacer = N','
			end
            select @art_col = @art_col + 1

			-- flush command if necessary
			exec dbo.sp_MSflush_command @cmd output, 0
       end
       select @this_col = @this_col + 1
    end

	-- save off cmd fragment
	exec dbo.sp_MSflush_command @cmd output, 1
go

raiserror('Creating procedure sp_MSscript_begintrig1', 0,1)
go
create procedure sp_MSscript_begintrig1
	@trigname      sysname,
	@objid         int,
	@procname      sysname,
	@filter_clause nvarchar(4000),
	@op_type       char(3) = 'ins' -- ins, upd, del
as
    declare @cmd       nvarchar(4000)
	declare @start     int
	declare @sub_len   int
	declare @qualname  nvarchar(512)

    exec sp_MSget_qualified_name @objid, @qualname OUTPUT

	-- construct trigger name
	select @cmd = N'create trigger ' + QUOTENAME(@trigname) + N' on ' + @qualname + N' '

	if @op_type = 'ins'
	    select @cmd = @cmd + N'for insert not for replication 
 as 
'
	else if @op_type = 'upd'
	    select @cmd = @cmd + N'for update not for replication 
 as
'
	else if @op_type = 'del'
	    select @cmd = @cmd + N'for delete not for replication 
 as
'

    exec dbo.sp_MSflush_command @cmd output, 1


    -- declare common local variables
	insert into #proctext(procedure_text) values 
		(N'declare @rc int, @retcode int, @connect_string nvarchar(2000), @rpc_proc nvarchar(4000), 
')
	insert into #proctext(procedure_text) values 
		(N'@rpc_types nvarchar(4000), @bitmap varbinary(4000)
')

    -- script variables used to retrieve data from inserted table
    if @op_type in ('ins', 'upd')
    begin
        insert into #proctext(procedure_text) values(N'declare ')
        exec dbo.sp_MSscript_params @objid, null, null, 0, null
        insert into #proctext(procedure_text) values(N' 
')
    end
    insert into #proctext(procedure_text) values(N'declare ')
    exec dbo.sp_MSscript_params @objid, null, '_old',  0, null

    insert into #proctext(procedure_text) values(N' 

')
    insert into #proctext(procedure_text) values(N'select @rc = @@ROWCOUNT 

')
		
	-- Optimization. Return immediately if no row changed
	-- This must be at the beginning of the trigger to @@rowcount be overwritten.
    insert into #proctext(procedure_text) values(N'if @rc = 0 return 

')
		

	insert into #proctext(procedure_text) values(N'select @bitmap = columns_updated()

')

	-- Partition check statement
	if @filter_clause IS NOT NULL
	begin
	    insert into #proctext(procedure_text) values (N'if exists (select * from inserted where not (')
	    
		-- break filter_clause into chunks of 255
		select @start = 1
		while @start < len(@filter_clause)
		begin
		    if len(@filter_clause) < 255
			    select @sub_len = len(@filter_clause)
			else
				select @sub_len = 255
		    select @cmd = substring(@filter_clause, @start, @sub_len)
			exec dbo.sp_MSflush_command @cmd output, 1
			select @start = @start + @sub_len
		end
			
		insert into #proctext(procedure_text) values (N')) 
 begin 
     exec sp_MSreplraiserror 21034
     goto FAILURE 
 end
')
	end
go

raiserror('Creating procedure sp_MSscript_begintrig2', 0,1)
go
create procedure sp_MSscript_begintrig2
    @objid       int, 
	@op_type     char(3) = 'ins' -- ins, upd, del
as
    declare @cmd nvarchar(4000)

    --select @cmd = N'if Objectproperty(@@procid, '
    if @op_type = 'ins' 
    insert into #proctext(procedure_text) values(N'if Objectproperty(@@procid,''TriggerInsertOrder'') != 1
 begin
     raiserror (21128, 16, 1)
     return 
 end

')

    else if @op_type = 'upd' 
    insert into #proctext(procedure_text) values(N'if Objectproperty(@@procid,''TriggerUpdate'') != 1
 begin
     raiserror (21129, 16, 1)
     return 
 end

')

    else if @op_type = 'del' 
    insert into #proctext(procedure_text) values(N'if Objectproperty(@@procid,''TriggerDeleteOrder'') != 1
 begin
     raiserror (21130, 16, 1)
     return 
 end

')


-- debug
--    insert into #proctext(procedure_text) values(N' ')
--	if @op_type = 'ins'
--	    insert into #proctext(procedure_text) 
--		    values(N'select ''SyncTran Insert Trigger fired on table'' = ' + N'''' + @source_table + N'''')
--	else if @op_type = 'upd'
--	    insert into #proctext(procedure_text) 
--		    values(N'select ''SyncTran Update Trigger fired on table'' = ' + N'''' + @source_table + N'''')
--	else if @op_type = 'del'
--	    insert into #proctext(procedure_text) 
--		    values(N'select ''SyncTran Delete Trigger fired on table'' = ' + N'''' + @source_table + N'''')

--	insert into #proctext(procedure_text) values(N'    , ''global nestlevel'' = trigger_nestlevel() ') 
--	insert into #proctext(procedure_text) values(N'    , ''local nestlevel'' = trigger_nestlevel(@@procid) ')

--    if @op_type = 'ins'
--	    insert into #proctext(procedure_text) values(N'    , ''fire_order'' = Objectproperty(@@procid, ''TriggerInsertOrder'') ')
--    if @op_type = 'upd'
--		insert into #proctext(procedure_text) values(N'    , ''fire_order'' = Objectproperty(@@procid, ''TriggerUpdateOrder'') ')
--    if @op_type = 'del'
--		insert into #proctext(procedure_text) values(N'    , ''fire_order'' = Objectproperty(@@procid, ''TriggerDeleteOrder'') ')	
-- debug

	-- Get rpc prefix
    -- Get rpc prefix
    insert into #proctext(procedure_text) values
		(N'exec @retcode = dbo.sp_MSget_publisher_rpc @@procid, @connect_string output
 if @retcode <>0 or @@error <> 0 goto FAILURE

')

    insert into #proctext(procedure_text) values(N'BEGIN DISTRIBUTED TRAN

') 
go

raiserror('Creating procedure sp_MSscript_endtrig', 0,1)
go
create proc sp_MSscript_endtrig
as
    declare @cmd nvarchar(4000)

    insert into #proctext(procedure_text) values(N'if @@trancount > 0 commit tran return

') 
   
    insert into #proctext(procedure_text) values(N'FAILURE: 
 if @@trancount > 0
 begin
     exec sp_MSreplraiserror 20512
     rollback tran
 end
') 
go

raiserror('Creating procedure sp_MSscript_trigger_variables', 0,1)
go

create procedure sp_MSscript_trigger_variables
    @objid int,
    @prefix char(1) = null, -- null or '@'
    @postfix varchar(4) = null,
    @indent int = 0,
    @spacer nvarchar(1) = N' ', 
    @bOutput_params tinyint = 0,  -- declare output params if necessary
    @identity_col sysname = null,
    @ts_col sysname = null,
    @include_type bit = 0,
	@set_nulls	bit = 0,
    @op_type char(3) = 'ins', -- 'ins, 'upd', 'del'
	@is_new		bit = 0,
	@primary_key_bitmap varbinary(4000) = NULL
as
    declare @cmd          nvarchar(4000)
    declare @colname      sysname
    declare @ccoltype     sysname
    declare @src_cols     int
    declare @this_col     int
    declare @art_col      int
    declare @rc           int
	declare @column		  nvarchar(4000)

    select @cmd = N''

    -- script cursor select variables
    select @src_cols = count(*) from syscolumns where id = @objid
    select @this_col = 1
	exec dbo.sp_MSpad_command @cmd output, @indent

    while @this_col <= @src_cols
    begin
        exec @rc = dbo.sp_MSget_colinfo @objid, @this_col, null, 0, @colname output, @ccoltype output
            
    if @rc = 0 and EXISTS (select name from syscolumns where id=@objid and colid=@this_col and iscomputed<>1)
    begin
        if @prefix is null
		begin
			
			if (@set_nulls = 1)
			begin
				-- Optimization:
				-- Get null or actual column name
				-- Note: the output is quoted.
				exec dbo.sp_MSget_synctran_column 
						@ts_col,
						@op_type, -- 'ins, 'upd', 'del'
						@is_new,
						@primary_key_bitmap,
						@colname,
						@this_col,
						@column output,
						0,
						@ccoltype
				select @cmd = @cmd + @spacer + @column + isnull(@postfix, N'')
			end
			else
				select @cmd = @cmd + @spacer + N'[' + @colname + isnull(@postfix, N'') + N']'
		end
		else
           select @cmd = @cmd + @spacer + isnull(@prefix, N'') + N'c' + RTRIM(convert(nvarchar(4), @this_col)) + isnull(@postfix, N'')

		if @include_type = 1
			begin
			declare @typestring nvarchar(100)
			exec dbo.sp_MSget_type @objid, @this_col, @colname output, @typestring OUTPUT
			select @cmd = @cmd +  N' ' + @typestring 
			end

        -- new vars of type timestamp and identity are declared as output params
        if (@bOutput_params = 1 and (@ccoltype = N'timestamp' or ColumnProperty(@objid, @colname, 'IsIdentity') = 1))
			   or
			   (@colname = @identity_col or @colname = @ts_col)
			begin
				-- YWU: Do this to avoid output in cursor declaration statement.
				-- The right thing seems to be set output only when bOutput_params is set
				-- but it seems not the way this sp is called.
				if @set_nulls = 0
					select @cmd = @cmd + N' output'
			end
			

        select @spacer = N','
        end
		
        exec dbo.sp_MSflush_command @cmd output, 0, @indent
	select @this_col = @this_col + 1
    end

    exec dbo.sp_MSflush_command @cmd output, 1, @indent
    insert into #proctext(procedure_text) values(N'
') 

go

raiserror('Creating procedure sp_MSscript_trigger_assignment', 0,1)
go

create procedure sp_MSscript_trigger_assignment
    @objid int,
	@postfix char(4) = null,
	@indent int = 0,
	@ts_col sysname,
    @op_type char(3), -- 'ins, 'upd', 'del'
	@is_new	bit,
	@primary_key_bitmap varbinary(4000)
as
    declare @cmd          nvarchar(4000)
	declare @colname      sysname
	declare @spacer       nvarchar(1)
	declare @ccoltype     sysname
	declare @src_cols     int
	declare @this_col     int
	declare @art_col      int
	declare @rc           int
	declare @column		  nvarchar(4000)

    -- script cursor select variables
    select @src_cols = count(*) from syscolumns where id = @objid
    select @spacer = N' '
    select @this_col = 1
	exec dbo.sp_MSpad_command @cmd output, @indent

    while @this_col <= @src_cols
    begin
        exec @rc = dbo.sp_MSget_colinfo @objid, @this_col, null, 0, @colname output, @ccoltype output
	    if @rc = 0  and EXISTS (select name from syscolumns where id=@objid and @this_col=colid and iscomputed<>1)
        begin

			-- Optimization:
			-- Get null or actual column name
			-- Note: the output is quoted.
			exec dbo.sp_MSget_synctran_column 
					@ts_col,
					@op_type, -- 'ins, 'upd', 'del'
					@is_new,
					@primary_key_bitmap,
					@colname,
					@this_col,
					@column output

			select @cmd = @cmd + @spacer + N'@c' + 
				convert(varchar(4), @this_col) + isnull(@postfix, N'') + 
				N' = ' + @column  
				
            select @spacer = N','
        end
		
        exec dbo.sp_MSflush_command @cmd output, 0, @indent
		select @this_col = @this_col + 1
    end

    exec dbo.sp_MSflush_command @cmd output, 1, @indent
    insert into #proctext(procedure_text) values(N'
') 

go

raiserror('Creating procedure sp_MSscript_trigger_fetch_statement', 0,1)
go

create procedure sp_MSscript_trigger_fetch_statement
    @objid   int, 
    @op_type char(3) = 'ins',
    @indent   int = 0
as
    declare @cmd          nvarchar(4000)

    exec dbo.sp_MSpad_command @cmd output, @indent
  
    -- script fetch statements
    if @op_type in ('ins', 'upd')
    begin
	    exec dbo.sp_MSpad_command @cmd output, @indent
		select @cmd = @cmd + (N'fetch next from rpl_ins_cursor into 
')
		exec dbo.sp_MSflush_command @cmd output, 1, @indent
		exec dbo.sp_MSscript_trigger_variables @objid, '@', null, @indent, ' '
	end

	if @op_type in ('ins')
	begin
	    exec dbo.sp_MSpad_command @cmd output, @indent
		select @cmd = @cmd + (N'fetch next from rpl_ins2_cursor into 
')
		exec dbo.sp_MSflush_command @cmd output, 1, @indent
        exec dbo.sp_MSscript_trigger_variables @objid, '@', '_old', @indent, ' '
	end

    if @op_type in ('upd', 'del')
    begin
		exec dbo.sp_MSpad_command @cmd output, @indent
		select @cmd = @cmd + (N'fetch next from rpl_del_cursor into 
')
		exec dbo.sp_MSflush_command @cmd output, 1, @indent
		exec dbo.sp_MSscript_trigger_variables @objid, '@', '_old', @indent, ' '
	end
go
 
raiserror('Creating procedure sp_MSscript_trigger_exec_rpc ', 0,1)
go
create procedure sp_MSscript_trigger_exec_rpc 
    @publisher   sysname,
    @publisherdb sysname,
    @procname   sysname,
    @proc_owner sysname,
    @objid       int, 
    @op_type     char(3) = 'ins', 
    @indent      int = 0,
    @identity_col sysname = null,
    @ts_col       sysname = null
as
    declare @cmd nvarchar(4000)
    declare @min_identity int
    declare @max_identity int

    insert into #proctext(procedure_text) values (N'    if @connect_string is null 
     begin 
')
	
    select @cmd = N'        exec @retcode = ' + 
        quotename(@publisher)	+ N'.' + 
	quotename(@publisherdb) + N'.' + 
	quotename(@proc_owner)	+ N'.' + 
	quotename(@procname) 
	-- 1st two variables are subscriber server name and database name for cycle detection
    select @cmd = @cmd + ' ' + 
	quotename(@@SERVERNAME) + N', ' + 
	quotename(db_name()) + N', 
'
    exec dbo.sp_MSflush_command @cmd, 1, @indent
    select @min_identity = @@identity

    if @op_type in ('ins', 'upd')
        exec dbo.sp_MSscript_trigger_variables @objid, '@', N'', @indent, N'', 0,  @identity_col, @ts_col

    if @op_type = 'upd'
	begin
        exec dbo.sp_MSscript_trigger_variables @objid, '@', '_old', @indent, ',', 0, null, null
		insert into #proctext(procedure_text) values (N', @bitmap')
	end

    else if @op_type = 'del'
        exec dbo.sp_MSscript_trigger_variables @objid, '@', '_old', @indent, ' ', 0, null, null

    select @max_identity = @@identity
	
    -- Raise friendly error.
    insert into #proctext(procedure_text) values (N'        
         if @@error <>0 or @retcode <> 0 
         begin 
             exec sp_MSreplraiserror 21054
             goto FAILURE 
         end
')
    
    -- End if @connect is null
    insert into #proctext(procedure_text) values (N'    end 
     else 
     begin 
')
	
    select @cmd = '        select @rpc_proc = N''declare @retcode int 
         exec @retcode = '' + N'
    select @cmd = @cmd + quotename('OpenDataSource(''SQLOLEDB'',N' ,'''') 
    select @cmd = @cmd + '+ '''''''' + replace(@connect_string, '''''''', '''''''''''''''') + N'''''''' + '
    select @cmd = @cmd + 'N'').'' + N''' 
    select @cmd = @cmd + quotename(@publisherdb)	+ '.'
    select @cmd = @cmd + quotename(@proc_owner)		+ '.'
    select @cmd = @cmd + quotename(@procname)		+ ''' + N'
    select @cmd = @cmd + quotename(quotename(@@SERVERNAME),'''')	+ ' + '','' + N'
    select @cmd = @cmd + quotename(quotename(db_name()),'''')		+ ' + '','' + ''
'
    exec dbo.sp_MSflush_command @cmd, 1, @indent

     -- Get parameters
    if @op_type in ('ins', 'upd')
        exec dbo.sp_MSscript_trigger_variables @objid, '@', N'', @indent, N'', 0,  @identity_col, @ts_col

    if @op_type = 'upd'
	begin
        exec dbo.sp_MSscript_trigger_variables @objid, '@', 'o', @indent, ',', 0, null, null
		insert into #proctext(procedure_text) values (N', @bitmap')
	end

    else if @op_type = 'del'
        exec dbo.sp_MSscript_trigger_variables @objid, '@', 'o', @indent, ' ', 0, null, null

    -- Must raise error right before exiting the dynamic exec so that it will be picked up.
    insert into #proctext(procedure_text) values 
        (N'            '' + '' if @@error <>0 or @retcode <> 0 exec sp_MSreplraiserror 21054''

')

    -- Get parameter datatypes
    insert into #proctext(procedure_text) values
		(N'        select @rpc_types = ''')
    if @op_type in ('ins', 'upd')
        exec dbo.sp_MSscript_trigger_variables @objid, '@', N'' , @indent, N'', 0,  @identity_col, @ts_col, 1
    if @op_type = 'upd'
        exec dbo.sp_MSscript_trigger_variables @objid, '@', 'o', @indent, ',', 0, null, null, 1
    else if @op_type = 'del'
        exec dbo.sp_MSscript_trigger_variables @objid, '@', 'o', @indent, ' ', 0, null, null, 1
    insert into #proctext(procedure_text) values (N'            ''')

    if @op_type = 'upd'
	begin
		insert into #proctext(procedure_text) values 
			(N' select @rpc_types = @rpc_types + '', @bitmap varbinary(4000)'' ')
	end

    -- make rpc call
    insert into #proctext(procedure_text) values 
        (N'        
         exec @retcode = dbo.sp_executesql @rpc_proc,  @rpc_types, 
')

    -- Get parameters again
    insert into #proctext(procedure_text) select procedure_text from #proctext
    where c1 > @min_identity and c1 <= @max_identity
    order by c1 asc

    insert into #proctext(procedure_text) values (N'        
         if @@error <>0 goto FAILURE
')

    -- end else
    insert into #proctext(procedure_text) values (N'     end
')
go

raiserror('Creating procedure sp_MSscript_trigger_update_checks', 0,1)
go

create procedure sp_MSscript_trigger_update_checks
    @objid int,
    @identity_col sysname,
    @ts_col       sysname,
    @op_type varchar(3) = 'ins', -- 'pk', 'ins', 'upd'
    @indent int = 0
as
    declare @cmd          nvarchar(4000)
    declare @colname      sysname
    declare @ccoltype     sysname
    declare @src_cols     int
    declare @this_col     int
    declare @rc           int
    declare @qualname     nvarchar(512)
    declare @indid        int
    declare @key          sysname
    declare @indkey       int


    if @op_type = 'pk'
    begin
		select @indkey = 1
		exec sp_MSget_qualified_name @objid, @qualname OUTPUT
        exec @indid = dbo.sp_MStable_has_unique_index @objid
        if @indid > 0
  	    begin
	        exec dbo.sp_MSpad_command @cmd output, @indent
	        while @indkey < 16 and index_col(@qualname, @indid, @indkey) is not null
            begin
                select @key = index_col(@qualname, @indid, @indkey)
                select @cmd = N'if update(' + @key + N')
'
                exec dbo.sp_MSflush_command @cmd output, 1, @indent
                insert into #proctext(procedure_text) values(N'begin
     exec sp_MSreplraiserror 20517
     goto FAILURE
 end 

')
                select @indkey = @indkey + 1
            end
        end
    end
    else
    begin
        -- Image cols
        select @src_cols = count(*) from syscolumns where id = @objid
        select @this_col = 1
	exec dbo.sp_MSpad_command @cmd output, @indent
   
        while @this_col <= @src_cols
        begin
            exec @rc = dbo.sp_MSget_colinfo @objid, @this_col, null, 1, @colname output, @ccoltype output
            if @rc = 0  and EXISTS (select name from syscolumns where id=@objid and @this_col=colid and iscomputed<>1)
            begin
                if @ccoltype in ('text','ntext','image')
                begin
    		    if @op_type = 'ins'
                    begin
                        select @cmd = N'if update(' +  @colname + ') 
'
                        exec dbo.sp_MSflush_command @cmd output, 1, 0
                        insert into #proctext(procedure_text) values(N'    exec sp_MSreplraiserror 20508
')
                    end
                    else if @op_type = 'upd'
                    begin
                        select @cmd = N'if update(' +  @colname + ') 
' 
                        exec dbo.sp_MSflush_command @cmd output, 1, 0
                        insert into #proctext(procedure_text) values(N'begin
     exec sp_MSreplraiserror 20509
     goto FAILURE 
 end

')
                    end
                end
            end
            select @this_col = @this_col + 1
        end
    end

    -- identity col
    if @op_type = 'upd' and @identity_col is not null
    begin
        select @cmd = N'if update(' +  @identity_col + N') 
'
        exec dbo.sp_MSflush_command @cmd, 1
        insert into #proctext(procedure_text) values(N'begin
     exec sp_MSreplraiserror 20510
     goto FAILURE
 end

')
    end
 
    -- timestamp col
    if @op_type = 'upd' and @ts_col is not null
	begin
        select @cmd = N'if update(' +  @ts_col + N') 
'
        exec dbo.sp_MSflush_command @cmd, 1
        insert into #proctext(procedure_text) values(N'begin
     exec sp_MSreplraiserror 20511
     goto FAILURE
 end

')
    end

go	

raiserror('Creating procedure sp_MSscript_trigger_updates', 0,1)
go
create procedure sp_MSscript_trigger_updates
    @identity_col sysname,
	@ts_col       sysname,
	@op_type      char(3) = 'ins', -- 'ins', 'del'
	@objid        int,
	@indent       int = 0
as
    declare @cmd nvarchar(4000)
	declare @col sysname
	declare @qualname nvarchar(512)

	if @op_type = 'upd'
	begin
		-- Script out pk var assigment that used in sp_MSscript_where_clause
		exec dbo.sp_MSscript_pkvar_assignment @objid, NULL, 1, @identity_col, @ts_col

		insert into #proctext(procedure_text) values(N'
	')
	end

    exec sp_MSget_qualified_name @objid, @qualname OUTPUT

    if @ts_col is not null
	begin
	    insert into #proctext(procedure_text) values(N' 
')
	    exec dbo.sp_MSpad_command @cmd output, @indent
		exec dbo.sp_MSget_col_position @objid, null, @ts_col, @col output
		select @cmd = @cmd + N'update ' + @qualname + N' set ' + @ts_col + N' = @' + @col
		exec dbo.sp_MSflush_command @cmd, 1

		exec dbo.sp_MSscript_where_clause @objid, null, 'trg pk', null, @indent, @op_type
	end

   if @op_type = 'ins' and @identity_col is not null
	begin
	    insert into #proctext(procedure_text) values(N' 
')
	    exec dbo.sp_MSpad_command @cmd output, @indent
		exec dbo.sp_MSget_col_position @objid, null, @identity_col, @col output
		select @cmd = @cmd + N'update ' + @qualname + N' set ' + @identity_col + N' = @' + @col
		exec dbo.sp_MSflush_command @cmd, 1

		exec dbo.sp_MSscript_where_clause @objid, null, 'trg pk', null, @indent, @op_type
	end
go

raiserror('Creating procedure sp_MSscript_singlerow_trigger', 0,1)
go
create procedure sp_MSscript_singlerow_trigger
    @objid        int,
	@publisher    sysname,
	@publisher_db sysname,
	@procname     sysname,
	@proc_owner	  sysname,
	@identity_col  sysname,
	@ts_col        sysname,
    @op_type char(3) = 'ins', -- 'ins, 'upd', 'del'
	@primary_key_bitmap varbinary(4000) = NULL
as	
	declare @colname      sysname
	declare @spacer       nvarchar(1)
	declare @ccoltype     sysname
	declare @src_cols     int
	declare @this_col     int
	declare @rc           int
	
    select @src_cols = count(*) from syscolumns where id = @objid

	if @op_type in ('ins', 'upd')
	    exec dbo.sp_MSscript_trigger_update_checks @objid, @identity_col, @ts_col, @op_type, 0

    insert into #proctext(procedure_text) values(N'if @rc = 1
 begin
')
    if @op_type in ('ins', 'upd')
        begin
            insert into #proctext(procedure_text) values(N'    select')
	    exec dbo.sp_MSscript_trigger_assignment @objid, null, 4, @ts_col, @op_type, 1, @primary_key_bitmap
            insert into #proctext(procedure_text) values(N'    from inserted

')
        end

        if @op_type in ('ins')
        begin
            insert into #proctext(procedure_text) values(N'    select')
            exec dbo.sp_MSscript_trigger_assignment @objid, '_old', 4, @ts_col, @op_type, 0, @primary_key_bitmap
            insert into #proctext(procedure_text) values(N'    from inserted

')
        end
        else if @op_type in ('upd', 'del')
        begin
            insert into #proctext(procedure_text) values(N'    select')
            exec dbo.sp_MSscript_trigger_assignment @objid, '_old', 4, @ts_col, @op_type, 0, @primary_key_bitmap
            insert into #proctext(procedure_text) values(N'    from deleted

')
        end
  
        exec dbo.sp_MSscript_trigger_exec_rpc @publisher, @publisher_db, @procname, @proc_owner, @objid, @op_type, 12, @identity_col, @ts_col
	    
        if @op_type in ('ins', 'upd')
	    exec dbo.sp_MSscript_trigger_updates @identity_col, @ts_col, @op_type, @objid, 4
	  
	insert into #proctext(procedure_text) values(N'end

')
go

raiserror('Creating procedure sp_MSscript_multirow_trigger', 0,1)
go
create procedure sp_MSscript_multirow_trigger
    @objid        int,
    @publisher    sysname,
    @publisher_db sysname,
    @procname     sysname,
    @proc_owner	  sysname,
    @identity_col  sysname,
    @ts_col        sysname,
    @op_type char(3) = 'ins', -- 'ins, 'upd', 'del'
	@primary_key_bitmap varbinary(4000) = NULL
as

    declare @cmd          nvarchar(4000)

    insert into #proctext(procedure_text) values(N'else
 begin
')
        -- setup cursor over inserted table for ins & upd triggers
        if @op_type in ('ins', 'upd')
        begin
            insert into #proctext(procedure_text) values(N'    declare rpl_ins_cursor CURSOR LOCAL FAST_FORWARD FOR select 
')

            exec dbo.sp_MSscript_trigger_variables @objid, null, null, 4, ' ',
				0,@identity_col, @ts_col,0, 1, @op_type, 1, @primary_key_bitmap
	    insert into #proctext(procedure_text) values(N'    from inserted for read only
')
            insert into #proctext(procedure_text) values(N'    open rpl_ins_cursor

')
        end

        if @op_type in ('ins')
        begin
            insert into #proctext(procedure_text) values(N'    declare rpl_ins2_cursor CURSOR LOCAL FAST_FORWARD FOR select 
')
            exec dbo.sp_MSscript_trigger_variables @objid, null, null, 4, ' '
            insert into #proctext(procedure_text) values(N'    from inserted for read only
')
            insert into #proctext(procedure_text) values(N'    open rpl_ins2_cursor

')
        end

        -- setup cursor over deleted table for  upd & del triggers
        if @op_type in ('upd', 'del')
        begin
            insert into #proctext(procedure_text) values(N'    declare rpl_del_cursor CURSOR LOCAL FAST_FORWARD FOR select 
')
            exec dbo.sp_MSscript_trigger_variables @objid, null, null, 4, ' ', 
				0,@identity_col, @ts_col,0, 1,  @op_type, 0, @primary_key_bitmap

            insert into #proctext(procedure_text) values(N'    from deleted for read only
')
            insert into #proctext(procedure_text) values(N'    open rpl_del_cursor

')
        end

        -- script fetch statement
        exec dbo.sp_MSscript_trigger_fetch_statement @objid, @op_type, 4

        insert into #proctext(procedure_text) values(N' 
')
        insert into #proctext(procedure_text) values(N'    while @@fetch_status <> -1
     begin
')
        exec dbo.sp_MSscript_trigger_exec_rpc @publisher, @publisher_db, @procname, @proc_owner, @objid, @op_type, 16, @identity_col, @ts_col
        if @op_type in ('ins', 'upd')
            exec dbo.sp_MSscript_trigger_updates @identity_col, @ts_col, @op_type, @objid, 8
	exec dbo.sp_MSscript_trigger_fetch_statement @objid, @op_type, 8
        insert into #proctext(procedure_text) values(N'    
 end
')

        if @op_type in ('ins', 'upd')
        begin
            insert into #proctext(procedure_text) values(N'    close rpl_ins_cursor
     deallocate rpl_ins_cursor
')
        end

     if @op_type in ('upd', 'del')
        begin
            insert into #proctext(procedure_text) values(N'    close rpl_del_cursor
     deallocate rpl_del_cursor
')
        end

	insert into #proctext(procedure_text) values(N'end
')
go

go

raiserror('Creating procedure sp_MSscript_sync_ins_trig', 0,1)
go
create procedure sp_MSscript_sync_ins_trig
    @objid		  int,
	@publisher    sysname,
	@publisher_db sysname,
	@trigname     sysname,
    @procname     sysname,
    @proc_owner   sysname,
	@identity_col sysname = NULL,
	@ts_col       sysname = NULL,
	@filter_clause nvarchar(4000)
as
	declare @colname      sysname
	declare @indid        int
    declare @cmd          nvarchar(4000)
	declare @ins_cmd      nvarchar(4000)
	declare @columns      binary(32)
	declare @outvars      nvarchar(4000)
	declare @rc           int
	declare @qualname     nvarchar(512)

    set nocount on

    exec sp_MSget_qualified_name @objid, @qualname OUTPUT

	if @ts_col in ('null','NULL')
		select @ts_col = null

	if @identity_col in ('null','NULL')
		select @identity_col = null

		
    if @ts_col is null
	begin
	    -- row compare method only supports updates
	    select N'create trigger ' + QUOTENAME(@trigname) + N' on ' + @qualname + N' for insert  not for replication 
' + 
		    N'as 
' + 
            N'    exec sp_MSreplraiserror 20518
' + 
            N'    rollback transaction
' 
	end
	else 
	begin
	    -- Can't insert table with timestamp or identity col if no unique index
	    exec @indid = dbo.sp_MStable_has_unique_index @objid	
	    if (@ts_col is not null or @identity_col is not null) and @indid = 0
		begin
			select N'create trigger ' + QUOTENAME(@trigname) + N' on ' + @qualname + N' for insert  not for replication ' + 
			    N'as 
' +
                N'    exec sp_MSreplraiserror 20519
' +
                N'    rollback transaction
' 
		end
        else 
	    begin
            -- Create temp table
	        create table #proctext ( c1 int identity NOT NULL, procedure_text nvarchar(4000) NULL)

	        -- 1st preamble common to all synctran procs
	        exec dbo.sp_MSscript_begintrig1 @trigname, @objid, @procname, @filter_clause, 'ins'
						
		    -- 2nd preamble common to all synctran procs
	        exec dbo.sp_MSscript_begintrig2 @objid, 'ins'

			-- script single row handling
			exec @rc = dbo.sp_MSscript_singlerow_trigger @objid,@publisher, @publisher_db, @procname, @proc_owner, @identity_col, @ts_col, 'ins'

			-- script multi-row handling
			exec @rc = dbo.sp_MSscript_multirow_trigger @objid, @publisher, @publisher_db, @procname, @proc_owner, @identity_col, @ts_col, 'ins'
 
            -- script end of trigger
		    exec dbo.sp_MSscript_endtrig 

			-- send fragments to client
			select procedure_text from #proctext order by c1 asc
		end


	end



go

raiserror('Creating procedure sp_MSscript_sync_upd_trig', 0,1)
go
create procedure sp_MSscript_sync_upd_trig
    @objid        int,
	@publisher    sysname,
	@publisher_db sysname,
	@trigname     sysname,
    @procname     sysname,
	@proc_owner   sysname,
	@identity_col sysname = NULL,
	@ts_col       sysname = NULL,
	@filter_clause nvarchar(4000),
    @primary_key_bitmap  varbinary(4000)
as
	declare @colname      sysname
	declare @indid        int
    declare @cmd          nvarchar(4000)
	declare @ins_cmd      nvarchar(4000)
	declare @columns      binary(32)
	declare @outvars      nvarchar(4000)
	declare @rc           int
	declare @qualname     nvarchar(512)

    set nocount on

    exec sp_MSget_qualified_name @objid, @qualname OUTPUT

	if @ts_col in ('null','NULL')
		select @ts_col = null

	if @identity_col in ('null','NULL')
		select @identity_col = null

    exec @indid = dbo.sp_MStable_has_unique_index @objid	
	if @ts_col is not null and @indid = 0
	begin
		select N'create trigger ' + QUOTENAME(@trigname) + N' on ' + @qualname + N' for update  not for replication ' + 
		    N'as 
' + 
            N'    exec sp_MSreplraiserror 20520
' + 
            N'    rollback transaction
' 
	end
    else 
	begin
        -- Create temp table
	    create table #proctext ( c1 int identity NOT NULL, procedure_text nvarchar(4000) NULL)

	    -- 1st preamble common to all synctran procs
	    exec dbo.sp_MSscript_begintrig1 @trigname, @objid, @procname, @filter_clause, 'upd'
						
		-- trigger nesting checks
		insert into #proctext(procedure_text) values(N' 
')
	    insert into #proctext(procedure_text) values(N'declare @trigger_op char(10)
')
		insert into #proctext(procedure_text) values(N'exec @retcode = dbo.sp_check_sync_trigger @@procid, @trigger_op OUTPUT 
')
	    insert into #proctext(procedure_text) values(N'if @retcode = 1 return 
' )

		-- prevent updating of unique index when 'row compare' conflict detection, since it would trickle
        -- back as a del/insert, and fail
		if @ts_col is null
		begin
		    insert into #proctext(procedure_text) values(N' 
')
		    exec dbo.sp_MSscript_trigger_update_checks @objid, null, null, 'pk', 0
		end

		-- 2nd preamble common to all synctran procs
	    exec dbo.sp_MSscript_begintrig2 @objid, 'upd'

		-- script single row handling
		exec @rc = dbo.sp_MSscript_singlerow_trigger @objid,@publisher, @publisher_db, @procname, @proc_owner, @identity_col, @ts_col, 'upd', @primary_key_bitmap

		-- script multi-row handling
		exec @rc = dbo.sp_MSscript_multirow_trigger @objid,@publisher, @publisher_db, @procname, @proc_owner, @identity_col, @ts_col, 'upd', @primary_key_bitmap
        -- script end of trigger
		exec dbo.sp_MSscript_endtrig 

	    -- send fragments to client
	    select procedure_text from #proctext order by c1 asc
	end

go

raiserror('Creating procedure sp_MSscript_sync_del_trig', 0,1)
go
create procedure sp_MSscript_sync_del_trig
    @objid        int,
	@publisher    sysname,
	@publisher_db sysname,
	@trigname     sysname,
    @procname     sysname,
	@proc_owner	  sysname,
	@identity_col sysname = NULL,
	@ts_col       sysname = NULL,
	@filter_clause nvarchar(4000),
    @primary_key_bitmap  varbinary(4000)
as
	declare @colname sysname
	declare @indid int
    declare @cmd          nvarchar(4000)
	declare @ins_cmd      nvarchar(4000)
	declare @columns      binary(32)
	declare @outvars      nvarchar(4000)
	declare @rc           int
	declare @qualname     nvarchar(512)

    set nocount on

    exec sp_MSget_qualified_name @objid, @qualname OUTPUT

	if @ts_col in ('null','NULL')
		select @ts_col = null

	if @identity_col in ('null','NULL')
		select @identity_col = null


    if @ts_col is null
	begin
	    -- row compare method only supports updates
	    select N'create trigger ' + QUOTENAME(@trigname) + N' on ' + @qualname + N' for delete  not for replication ' + 
		    N'as 
' + 
            N'    exec sp_MSreplraiserror 20518
' + 
            N'    rollback transaction
'  
	end
	else 
	begin
	    exec @indid = dbo.sp_MStable_has_unique_index @objid	
        -- Create temp table
        create table #proctext ( c1 int identity NOT NULL, procedure_text nvarchar(4000) NULL)

        -- 1st preamble common to all synctran procs
        exec dbo.sp_MSscript_begintrig1 @trigname, @objid, @procname, @filter_clause, 'del'
					
		-- 2nd preamble common to all synctran procs
	    exec dbo.sp_MSscript_begintrig2 @objid, 'del'

		-- script single row handling
		exec @rc = dbo.sp_MSscript_singlerow_trigger @objid,@publisher, @publisher_db, @procname, @proc_owner, @identity_col, @ts_col, 'del', @primary_key_bitmap

		-- script multi-row handling
		exec @rc = dbo.sp_MSscript_multirow_trigger @objid,@publisher, @publisher_db, @procname, @proc_owner, @identity_col, @ts_col, 'del', @primary_key_bitmap
 
        -- script end of trigger
		exec dbo.sp_MSscript_endtrig 

    	-- send fragments to client
	    select procedure_text from #proctext order by c1 asc
	end

go

raiserror('Creating procedure sp_MSget_synctran_column', 0,1)
go
create procedure sp_MSget_synctran_column
	@ts_col sysname,
    @op_type char(3), -- 'ins, 'upd', 'del'
	@is_new	bit,
	@primary_key_bitmap varbinary(4000),
	@colname sysname,
    @this_col int,
    @column nvarchar(4000) output,
	@from_proc bit = 0,
	@coltype sysname = NULL,
	@type	varchar(10) = NULL
as
	declare @bytestr      nvarchar(10)
	declare @bitstr       nvarchar(10)
	declare @typed_null	  nvarchar(255)

	if @coltype is null
		select @typed_null = 'NULL'
	else
		select @typed_null = 'convert(' + @coltype + ', NULL)' 

	-- Optimization:
	-- If the column value is not needed, we set the corresponding
	-- param to null to reduce the network traffic. Here is the rule:

	-- For new values in update trigger,
	--	Set the param to column value or null depending on whether or
	--  or the column is updated.
	-- For old values 
	--	if ts col is replicated and the current column is not the ts col
	--	and the column is not in primary key, set the param to null
	-- For other cases
	--	set the param to column values.

	-- Called by proc
	if @type = 'pk_var'
	begin
		select @bytestr = convert( nvarchar, 1 + (@this_col-1) / 8 )
		select @bitstr =  convert( nvarchar, power(2, (@this_col-1) % 8 ) )

		select @column = N'case substring(@bitmap,' 
			+ @bytestr + N',1) & ' + @bitstr +  
			N' when ' + @bitstr + N' then ' + N'@c'+ convert( nvarchar, @this_col ) + 
			N' else ' + N'@c'+ convert( nvarchar, @this_col )  + N'_old end'
	end
	else if (@from_proc = 1)
	begin
		select @bytestr = convert( nvarchar, 1 + (@this_col-1) / 8 )
		select @bitstr =  convert( nvarchar, power(2, (@this_col-1) % 8 ) )

		select @column = N'case substring(@bitmap,' 
			+ @bytestr + N',1) & ' + @bitstr +  
			N' when ' + @bitstr + N' then ' + N'@c'+ convert( nvarchar, @this_col ) + 
			N' else [' + @colname + N'] end'
	end
	-- Called in trigger,
	else if (@is_new = 1) and (@op_type = 'upd')
	begin
		-- @bitmap is set using columns_updated() at the beginning
		-- of the trigger.
		select @bytestr = convert( nvarchar, 1 + (@this_col-1) / 8 )
		select @bitstr =  convert( nvarchar, power(2, (@this_col-1) % 8 ) )
		
		select @column = N'case substring(@bitmap,' + @bytestr + N',1) & ' + @bitstr +  
			N' when ' + @bitstr + N' then [' + @colname + N'] ' + 
			N' else ' + @typed_null 
			+' end'
	end
	else if @is_new = 0 and @ts_col is not null and @colname <> @ts_col and
		(substring(@primary_key_bitmap, 1 + (@this_col-1) / 8 , 1) &
			power(2, (@this_col-1) % 8 )) = 0
		select @column =  @typed_null
	else 
		select @column = N'[' + @colname  + N'] '
	
	-- Add a new line
	select @column = @column + N'
	'
go

raiserror('Creating procedure sp_addsynctriggers', 0,1)
go

CREATE PROCEDURE sp_addsynctriggers 
    @sub_table       sysname,			-- table name 
	@sub_table_owner sysname,			-- table owner
    @publisher      sysname,            -- publishing server name
    @publisher_db   sysname,            -- publishing database name. If NULL then same as current db
    @publication	sysname,			-- publication name.
    @ins_proc       sysname,
    @upd_proc       sysname,
    @del_proc       sysname,
    @proc_owner		sysname,
    @identity_col   sysname = 'NULL', 
    @ts_col         sysname = 'NULL',
    @filter_clause  nvarchar(4000) = 'NULL',
    @primary_key_bitmap  varbinary(4000)
AS
    set nocount on

    declare @db                  sysname
    declare @trigname            sysname
    declare @ins_trig            sysname
    declare @upd_trig            sysname
	declare @del_trig            sysname
	declare @dbname              sysname
	declare @ccols               int
    declare @cnt                 int
    declare @retcode 	         int
	declare @cmd                 nvarchar(4000)
    declare @merge_pub_object_bit	int
    declare @synctran_bit		int
	declare @object_id			int
	declare @bitmap_str			varchar(8000)
	declare @constraint_name	sysname
	declare @quoted_name		nvarchar(500)
	declare @qualname		    nvarchar(500)

	select @merge_pub_object_bit 	= 128
	select @synctran_bit			= 256

	--  Security Check
    EXEC @retcode = dbo.sp_MSreplcheck_subscribe
    IF @@ERROR <> 0 or @retcode <> 0
	RETURN(1)

    -- Dist Agent executes this sproc with 'implicit transasctions on'.
    -- We take care of our own transactions boundaries to get out of tran 
    while @@trancount > 0 commit tran

	-- check valid server and database setting
	-- 1. nested trigger have to be on
	if exists (select * from master..sysconfigures where config = 115 and value = 0)
	begin
        raiserror(21081, 16, 1)
        return (1)
	end

	-- 2. db option: recursive trigger have to be off
	if DATABASEPROPERTY(db_name(), N'IsRecursiveTriggersEnabled') <> 0
	begin
        raiserror(21082, 16, 1)
        return (1)
	end	
	
	-- 2. db compatibility level have to be 7.0
	if exists (select * from master..sysdatabases where dbid = db_id() and 
		cmptlevel < 70)
	begin
        raiserror(21083, 16, 1)
        return (1)
	end	
	
	if lower(@sub_table_owner) = N'null'
		select @qualname = QUOTENAME(@sub_table)		
	else
		select @qualname = QUOTENAME(@sub_table_owner) + N'.' + QUOTENAME(@sub_table)

	-- Verify that table exists 
	select @object_id = object_id (@qualname)
	if @object_id is null
    begin
        raiserror(20507, 16, 1, @qualname, 'sp_addsynctriggers')
        return (1)
    end
	

	-- Add default to timestamp and identity column
	select @constraint_name = 'MSrepl_synctran_ts_default_' + convert(nvarchar(10), @object_id)
	select @quoted_name = quotename(@ts_col)
	if @ts_col is not null and @ts_col not in ('null','NULL') and not exists
		(select * from sysobjects where name = @constraint_name)
	begin
		exec ('alter table ' + @qualname + 
			' add constraint ' + @constraint_name + 
			' default 0 for ' + @quoted_name )
		if @@ERROR<>0 return 1
	end

	select @constraint_name = 'MSrepl_synctran_identity_default_' + convert(nvarchar(10), @object_id)
	select @quoted_name = quotename(@identity_col)
	if @identity_col is not null and @identity_col not in ('null','NULL') and not exists
		(select * from sysobjects where name = @constraint_name)
	begin
		exec ('alter table ' + @qualname + 
			' add constraint ' + @constraint_name + 
			' default 0 for ' + @quoted_name )
		if @@ERROR<>0 return 1
	end

	-- If MSsubscription_properties table does not exists, create on.
	exec @retcode = dbo.sp_MScreate_sub_tables
	IF @@ERROR <> 0 or @retcode <> 0
		RETURN(1)

	-- If no entry in MSsubscription_properties for this publication, add one.

	IF NOT EXISTS (select * from MSsubscription_properties 
            where UPPER(publisher) = UPPER(@publisher)
				and publisher_db =  @publisher_db
				and publication = @publication) 
	BEGIN
		-- Use status rpc for local publisher, see bug 39385
		declare @security_mode int
		declare @login sysname
		if UPPER(@@servername) = UPPER(@publisher)
		begin
			select @security_mode = 2
		end
		else
		begin
			select @security_mode = 0
			select @login = 'sa'
		end

		exec @retcode = dbo.sp_link_publication
			@publisher = @publisher,
			@publisher_db = @publisher_db,
			@publication = @publication,
			@security_mode = @security_mode,
			@login = @login,
			@password = [REDACTED]
		IF @@ERROR <> 0 or @retcode <> 0
			RETURN(1)
	END

	  
    if exists (select * from sysobjects where 
		replinfo & @merge_pub_object_bit <> 0 and
		id = @object_id)
	begin
        raiserror(21063, 16, 1, @qualname)
        return (1)
	end

	-- Generate trigger names
        select @trigname = RTRIM(SUBSTRING(@sub_table,1,110))
	select @ins_trig = N'trg_MSsync_ins_' + @trigname 
	select @upd_trig = N'trg_MSsync_upd_' + @trigname 
	select @del_trig = N'trg_MSsync_del_' + @trigname 

	-- check uniqueness of names and revert to ugly guid-based name if friendly name already exists
	if exists (select name from sysobjects where name in (@ins_trig, @upd_trig, @del_trig))
        begin
            declare @guid_name nvarchar(36)
            select @guid_name =  convert (nvarchar(36), newid())
		select @ins_trig = 'trg_MSsync_ins_' + @guid_name
		select @upd_trig = 'trg_MSsync_upd_' + @guid_name
		select @del_trig = 'trg_MSsync_del_' + @guid_name
        end

	exec @retcode = master..xp_varbintohexstr @primary_key_bitmap, @bitmap_str output
	if @retcode <> 0 or @@error <> 0
		return 1
/*
	exec ('if exists (select * from sysobjects where name = N''' + @ins_trig + N''' and xtype = N''TR'')
        drop trigger ' + @ins_trig)
    exec ('if exists (select * from sysobjects where name = N''' + @upd_trig + N''' and xtype = N''TR'')
        drop trigger ' + @upd_trig)
    exec ('if exists (select * from sysobjects where name = N''' + @del_trig + N''' and xtype = N''TR'')
        drop trigger ' + @del_trig)

*/
    -- We are now going to create triggers, so start a transaction
    begin tran

        -- Call out to individual create trigger routines
	    select @dbname = db_name()
	    select @cmd = 'sp_MSscript_sync_ins_trig ' + 
		    convert( nvarchar, @object_id )  + ', ' + 
			quotename(@publisher)     + ', ' + 
			quotename(@publisher_db)  + ', ' + 
		    quotename(@ins_trig)      + ', ' + 
			quotename(@ins_proc)      + ', ' + 
			quotename(@proc_owner)	  + ', ' + 
			quotename(@identity_col)  + ', ' + 
			quotename(@ts_col)        
		if @filter_clause in ('NULL', 'null')
		    select @cmd = @cmd + ', null' 
		else 
            select @cmd = @cmd + ', N''' + replace (@filter_clause,'''','''''')  + ''''


	    exec master..xp_execresultset @cmd, @dbname
		IF @@ERROR <> 0
			goto UNDO

	    select @cmd = 'sp_MSscript_sync_upd_trig ' + 
		    convert( nvarchar, @object_id )  + ', ' + 
			quotename(@publisher)     + ', ' + 
			quotename(@publisher_db)  + ', ' + 
		    quotename(@upd_trig)      + ', ' + 
			quotename(@upd_proc)      + ', ' + 
			quotename(@proc_owner)	   + ', ' + 
			quotename(@identity_col)  + ', ' + 
			quotename(@ts_col)        
		if @filter_clause in ('NULL', 'null')
		    select @cmd = @cmd + ', null' 
		else 
            select @cmd = @cmd + ', N''' + replace (@filter_clause,'''','''''')  + ''''
									
		-- Update need primary key bitmap
         select @cmd = @cmd + ', ' + @bitmap_str
	    
		 exec master..xp_execresultset @cmd, @dbname
		IF @@ERROR <> 0
			goto UNDO


	    select @cmd = 'sp_MSscript_sync_del_trig ' + 
		    convert( nvarchar, @object_id )  + ', ' + 
			quotename(@publisher)     + ', ' + 
			quotename(@publisher_db)  + ', ' + 
		    quotename(@del_trig)      + ', ' + 
			quotename(@del_proc)      + ', ' + 
			quotename(@proc_owner)	   + ', ' + 
			quotename(@identity_col)  + ', ' + 
			quotename(@ts_col)        
		if @filter_clause in ('NULL', 'null')
		    select @cmd = @cmd + ', null' 
		else 
            select @cmd = @cmd + ', N''' + replace (@filter_clause,'''','''''')  + ''''			

		-- Delete need primary key bitmap
         select @cmd = @cmd + ', ' + @bitmap_str
	    exec master..xp_execresultset @cmd, @dbname
		IF @@ERROR <> 0
			goto UNDO


	/*
	**	Create system table MSreplication_objects if it does not exist
	*/
		IF NOT EXISTS (SELECT * FROM sysobjects WHERE 
			type = 'U' AND name = 'MSreplication_objects')
			BEGIN
				CREATE TABLE dbo.MSreplication_objects
				(
				publisher sysname NULL,
				publisher_db sysname NULL,
       			publication sysname NULL, 
				object_name	sysname NOT NULL,
				object_type	char(2) NOT NULL
				)
				IF @@ERROR <> 0
					begin
						rollback transaction 
						return (1)
					end
				EXEC dbo.sp_MS_marksystemobject 'MSreplication_objects'
			END


		-- Mark procedures as system procs so they don't show up in the UI
		select @cmd = 'exec dbo.sp_MS_marksystemobject ' + quotename(@ins_trig)
		exec (@cmd)
		IF @@ERROR <> 0
			goto UNDO

		insert into MSreplication_objects(publisher, publisher_db, publication, object_name, object_type)
					values(@publisher, @publisher_db, @publication, @ins_trig, 'T')
		IF @@ERROR <> 0
			goto UNDO

		select @cmd = 'exec dbo.sp_MS_marksystemobject ' + quotename(@upd_trig)
		exec (@cmd)
		IF @@ERROR <> 0
			goto UNDO

		insert into MSreplication_objects(publisher, publisher_db, publication, object_name, object_type)
					values(@publisher, @publisher_db, @publication, @upd_trig, 'T')
		IF @@ERROR <> 0
			goto UNDO

		select @cmd = 'exec dbo.sp_MS_marksystemobject ' + quotename(@del_trig)
		exec (@cmd)
		IF @@ERROR <> 0
			goto UNDO

		insert into MSreplication_objects(publisher, publisher_db, publication, object_name, object_type)
					values(@publisher, @publisher_db, @publication, @del_trig, 'T')
		IF @@ERROR <> 0
			goto UNDO

		-- Mark the table for warnings in BCP
		update sysobjects set replinfo = replinfo | @synctran_bit where
			id = @object_id
	-- commit tran
	commit tran
	return (0)
UNDO:
	if @@trancount <> 0
		rollback tran
	return(1)
go

raiserror('Creating procedure sp_helpreplicationdboption', 0,1)
go

CREATE PROCEDURE sp_helpreplicationdboption
        @dbname sysname = '%', @type sysname = 'replication allowed'
    AS

    SET NOCOUNT ON

    /*
    ** Declarations.
    */

    DECLARE @retcode int, @typebit int
    
    /* bit to distinguish distribution databases */
    DECLARE @distbit int
    SELECT @distbit = 16

	DECLARE @dbowner bit
	SELECT @dbowner = 0
	DECLARE @replication_db sysname
				
	-- bug 24437 don't do security check.

    if (lower(@type) like 'publish%')
       select @typebit = 1
    else if (lower(@type) like 'subscribe%')
       select @typebit = 2
    else if (lower(@type) like 'merge publish%')
       select @typebit = 4
    else if (lower(@type) like 'merge subscribe%')
       select @typebit = 8
    else if (lower(@type) like 'replication allowed%')
        select @typebit = 0
    else        
        begin
            raiserror(14091,-1,-1)
            return 1
        end

    /*
    ** Parameter Check:  @dbname.
    ** Check to make sure that the database name conforms to the rules
    ** for identifiers.
    */

    IF @dbname <> '%'
       BEGIN
          EXECUTE @retcode = dbo.sp_validname @dbname

          IF @@ERROR <> 0 OR @retcode <> 0
            RETURN (1)
       END

    /*
    ** Show databases with this option enabled.
    */
    CREATE TABLE #replicationdbs (name sysname NOT NULL, id int identity NOT NULL, transpublish bit not null, mergepublish bit not null, dbowner bit not null)
    if @typebit <> 0
        begin

			INSERT INTO #replicationdbs (name, transpublish, mergepublish, dbowner)
                SELECT name, 
				case when (category & 1) <> 0 then 1 else 0 end,
				case when (category & 4) <> 0 then 1 else 0 end,
				@dbowner
                FROM master..sysdatabases
                   WHERE name LIKE @dbname
					AND (category & @typebit) <> 0 and
					(isnull(databaseproperty(name, N'issuspect'), 0) = 0 and isnull(databaseproperty(name, N'isshutdown'), 0) = 0)

			DECLARE hCdboinfo CURSOR LOCAL FAST_FORWARD FOR
				SELECT name FROM #replicationdbs
				FOR READ ONLY
			OPEN hCdboinfo
			FETCH hCdboinfo INTO @replication_db
			WHILE (@@fetch_status <> -1)
			BEGIN
				EXEC @retcode = sp_MSrepl_isdbowner @replication_db
				IF (@retcode IS NOT NULL) AND (@retcode <> 0)
				BEGIN
					UPDATE #replicationdbs set dbowner = 1 where name = @replication_db
				END
				FETCH hCdboinfo INTO @replication_db
			END
			CLOSE hCdboinfo
			DEALLOCATE hCdboinfo

            SELECT * FROM #replicationdbs
        end            
    else
        begin
            DECLARE @db_category int

            /* Filter out distribution databases */
            DECLARE hC  CURSOR LOCAL FAST_FORWARD FOR 
                SELECT name, category FROM master..sysdatabases WHERE name LIKE @dbname
                    AND (category & @distbit) = 0  and
					(isnull(databaseproperty(name, N'issuspect'), 0) = 0 and isnull(databaseproperty(name, N'isshutdown'), 0) = 0)
			FOR READ ONLY
            OPEN hC
            FETCH hC INTO @replication_db, @db_category
            WHILE (@@fetch_status <> -1)
                BEGIN
                    if @replication_db <> 'master' AND @replication_db <> 'model'
                        AND @replication_db <> 'tempdb' AND @replication_db <> 'msdb'
                        AND @replication_db <> 'MSSQLWeb'
					BEGIN
						EXEC @retcode = sp_MSrepl_isdbowner @replication_db
						IF (@retcode IS NOT NULL) AND (@retcode <> 0)
						BEGIN
							SELECT @dbowner = 1
						END
						ELSE
						BEGIN
							SELECT @dbowner = 0
						END
						INSERT INTO #replicationdbs (name, transpublish, mergepublish, dbowner) VALUES (@replication_db,
							case when (@db_category & 1) <> 0 then 1 else 0 end,
							case when (@db_category & 4) <> 0 then 1 else 0 end,
							@dbowner)
					END
                    FETCH hC INTO @replication_db, @db_category
                END

            CLOSE hC
            DEALLOCATE hC

            SELECT * FROM #replicationdbs
        end
        DROP TABLE #replicationdbs
go

raiserror('Creating procedure sp_MScheck_agent_instance', 0,1)
GO
CREATE PROCEDURE sp_MScheck_agent_instance
@application_name sysname,
@agent_type int = NULL

as
	declare @count_pro int
	set nocount on
	select @count_pro = count(*) from master..sysprocesses where 
		program_name = @application_name
	if @agent_type = 3
	begin
		-- The distribution agent will before connecting to the publisher with unique 
		-- application name
		if @count_pro > 0
			raiserror (21036, 16, -1, 'distribution')
	end
	else if @agent_type = 4
	begin
		-- The merge agent will connect to the publisher with unique application name
		-- then call this procedure
		if @count_pro > 1 
			raiserror (21036, 16, -1, 'merge')
	end
	else if @agent_type = 1
	begin
		-- The snapshot agent will connect to the distributiondb with unique application name
		-- then call this procedure
		if @count_pro > 1 
			raiserror (21036, 16, -1, 'snapshot')
	end
	else if @agent_type = 2
	begin
		-- The logreader agent will connect to the distributiondb with unique application name
		-- then call this procedure
		if @count_pro > 1 
			raiserror (21036, 16, -1, 'logreader')
	end
go

raiserror('Creating procedure sp_MSpublicationcleanup', 0,1)
GO

CREATE PROCEDURE sp_MSpublicationcleanup (
	@publication 		sysname,
	@publisher_db		sysname,
	@publisher			sysname = @@servername
	) AS
	declare @pubid 		uniqueidentifier
	declare @parentid 	uniqueidentifier
	declare @artid 		uniqueidentifier
	declare @retcode	smallint

	/*
    ** Security Check
    */
    EXEC @retcode = dbo.sp_MSreplcheck_publish
    IF @@ERROR <> 0 or @retcode <> 0
        return (1)

	/* This only gets called after database is enable to subscribe, so sysmergepublications should exist */
	select @pubid = pubid, @parentid = parentid FROM sysmergepublications 
		WHERE name = @publication and UPPER(publisher)=UPPER(@publisher) and publisher_db = @publisher_db

	/* Normal case - nothing to cleanup, just return */
	if @pubid is null
		return (1)

	/* Clean up the articles for this publication, and delete the row */
	select @artid = artid FROM sysmergearticles WHERE pubid = @pubid
	while @artid is not null
		begin
		if not exists (select * from sysmergearticles WHERE artid = @artid and pubid <> @pubid)
			begin
				exec @retcode=sp_MSarticlecleanup @pubid, @artid
				if @retcode<>0 or @@ERROR<>0 return (1)
			end
		delete from sysmergearticles where artid = @artid and pubid = @pubid
		set @artid = NULL
		select @artid = artid FROM sysmergearticles WHERE pubid = @pubid
		end
		
	/* Now clean up any traces in other system tables */
	

	delete from MSmerge_genhistory where pubid = @pubid
	delete from MSmerge_replinfo where repid in (select subid from sysmergesubscriptions where pubid = @pubid and status <> 2)

	delete from sysmergesubscriptions where pubid = @pubid and status <> 2
	delete from sysmergepublications where pubid = @pubid
	delete from sysmergeschemachange where pubid = @pubid
GO
exec dbo.sp_MS_marksystemobject sp_MSpublicationcleanup
go

grant execute on dbo.sp_MSpublicationcleanup to public
go

raiserror('Creating procedure sp_MSarticlecleanup', 0,1)
GO

create procedure sp_MSarticlecleanup
	(@pubid uniqueidentifier, @artid uniqueidentifier)
as
	set nocount on
	declare @source_table 	nvarchar(258)
	declare @conflict_table nvarchar(258)
	declare @ownername 		sysname
	declare @objectname 	sysname
	declare @tablenick		int
	declare @objid 			int
	declare @sync_objid 	int
	declare @view_type		int
	declare @tsview			nvarchar(50)
	declare @guidstr		nvarchar(50)
	declare @csview			nvarchar(50)
	declare @viewname		nvarchar(258)
	declare @retcode		smallint
	declare @qualified_name	nvarchar(258)
	
	-- to be called after article is set up in a subscriber

	/*
    ** Security Check
    */
    EXEC @retcode = dbo.sp_MSreplcheck_publish
    IF @@ERROR <> 0 or @retcode <> 0
        return (1)

	select @objid = max(objid) from sysmergearticles where artid = @artid

	-- get owner name, and table name
	select @objectname = name, @ownername = user_name(uid)
		from sysobjects	where id = @objid

	-- construct the qualified table name
	select @source_table = @ownername + '.' + @objectname

	exec @retcode=sp_MSguidtostr @artid, @guidstr out
	if @retcode<>0 or @@ERROR<>0 return (1)
	
	-- get the insert, update and conflict proc names from sysmergearticles
	select 	@sync_objid = sync_objid, 
			@view_type = view_type, 
			@tablenick = nickname,
			@conflict_table = conflict_table 
		from sysmergearticles where
			pubid = @pubid and artid = @artid

	/*
	** We are not owner_qualifed this conflict table because it is created by snapshot agent
	*/
	select @qualified_name = QUOTENAME(@conflict_table)

	/* Drop the conflict table */
	if (@conflict_table IS NOT NULL) and exists (select * from sysobjects where
			name = @conflict_table and type = 'U')
		begin
			exec ('drop table ' + @qualified_name)
			if @@ERROR<>0 return (1)
		end

	select @qualified_name = QUOTENAME(@ownername) + '.' + QUOTENAME(@conflict_table)

	/* Drop the article procs */
	exec @retcode=sp_MSdroparticleprocs @pubid, @artid
	if @@ERROR<>0 or @retcode<>0 return (1)

	/* Drop the article triggers */
	exec @retcode=sp_MSdroparticletriggers @source_table
	if @@ERROR<>0 or @retcode<>0 return (1)

	exec @retcode=sp_MSunmarkreplinfo @objectname, @ownername
	if @@ERROR<>0 or @retcode<>0 return (1)

	/* If the article's has a temporary ( view type = 2) or a permanent view (view_type = 1 ) drop the sync object */
	if (@view_type = 1 OR @view_type = 2)
		begin
			select @viewname = sysobjects.name from sysobjects where 
				ObjectProperty (sysobjects.id, 'IsView') = 1 
				and ObjectProperty (sysobjects.id, 'IsMSShipped') = 1 
				and sysobjects.id = @sync_objid
			if @viewname IS NOT NULL
				begin
					select @ownername = user_name(uid) from sysobjects where name=@viewname
					set @viewname = QUOTENAME(@ownername) + '.' + QUOTENAME(@viewname)
					exec ('drop view ' + @viewname)
					if @@ERROR<>0 return (1)
				end
		end

	/*
	** Drop the views created for MSmerge_contents and MSmerge_tombstone before dropping these two tables
	*/
	set @csview = 'ctsv_' + @guidstr
	set @tsview = 'tsvw_' + @guidstr
	if EXISTS (select * from sysobjects where name=@csview and type='V')
	BEGIN
		select @ownername = user_name(uid) from sysobjects where  name=@csview
		select @viewname = QUOTENAME(@ownername) + '.' + QUOTENAME(@csview)
		exec ('drop view ' + @viewname)
			if @@ERROR<>0 return (1)
	END
		
	if EXISTS (select * from sysobjects where name=@tsview and type='V')
	BEGIN
		select @ownername = user_name(uid) from sysobjects where  name=@tsview
		select @viewname = QUOTENAME(@ownername) + '.' + QUOTENAME(@tsview)
		exec ('drop view ' + @viewname)
			if @@ERROR<>0 return (1)
	END

	/* Delete from contents, tombstone, delete conflicts */
	delete from MSmerge_contents where tablenick = @tablenick
	delete from MSmerge_tombstone where tablenick = @tablenick
	delete from MSmerge_delete_conflicts where tablenick = @tablenick
GO

exec dbo.sp_MS_marksystemobject sp_MSarticlecleanup
go

grant execute on dbo.sp_MSarticlecleanup to public
go

raiserror('Creating procedure sp_MSdroparticleprocs', 0,1)
GO

create procedure sp_MSdroparticleprocs
	(@pubid uniqueidentifier, @artid uniqueidentifier)
as
	set nocount on
	declare @ins_procname 	sysname
	declare @upd_procname 	sysname
	declare @conf_procname 	sysname
	declare @sel_procname	sysname
	declare @tmp_procname	nvarchar(260)
	declare @view_sel_proc 	sysname
	declare @owner			sysname

	declare @objid			int
	
	-- get the insert, update and conflict proc names from sysmergearticles
	select @ins_procname = insert_proc,	
			@upd_procname = update_proc, 
			@sel_procname = select_proc,
			@conf_procname = ins_conflict_proc,
			@view_sel_proc = view_sel_proc,
			@objid = objid
		from sysmergearticles where
			pubid = @pubid and artid = @artid

	if (@ins_procname IS NOT NULL) and exists (select * from sysobjects where
			name = @ins_procname and type = 'P')
		begin
			select @owner = user_name(uid) from sysobjects where name=@ins_procname
			select @tmp_procname = QUOTENAME(@owner) + '.' + QUOTENAME(@ins_procname)
			exec ('drop proc ' + @tmp_procname)
			if @@ERROR<>0 return (1)
			update sysmergearticles set insert_proc = NULL where pubid=@pubid and artid=@artid
		end
	if (@upd_procname IS NOT NULL) and exists (select * from sysobjects where
			name = @upd_procname and type = 'P')
		begin
			select @owner = user_name(uid) from sysobjects where name=@upd_procname
			select @tmp_procname = QUOTENAME(@owner) + '.' + QUOTENAME(@upd_procname)
			exec ('drop proc ' + @tmp_procname)
			if @@ERROR<>0 return (1)
			update sysmergearticles set update_proc = NULL where pubid=@pubid and artid=@artid

		end
	if (@sel_procname IS NOT NULL) and exists (select * from sysobjects where
			name = @sel_procname and type = 'P')
		begin
			select @owner = user_name(uid) from sysobjects where name=@sel_procname
			select @tmp_procname = QUOTENAME(@owner) + '.' + QUOTENAME(@sel_procname)
			exec ('drop proc ' + @tmp_procname)
			if @@ERROR<>0 return (1)
			update sysmergearticles set select_proc = NULL where pubid=@pubid and artid=@artid
		end

	if (@view_sel_proc IS NOT NULL) and exists (select * from sysobjects where
			name = @view_sel_proc and type = 'P')
		begin
			select @owner = user_name(uid) from sysobjects where name=@view_sel_proc
			select @tmp_procname = QUOTENAME(@owner) + '.' + QUOTENAME(@view_sel_proc)
			exec ('drop proc ' + @tmp_procname)
			if @@ERROR<>0 return (1)
			update sysmergearticles set view_sel_proc = NULL where pubid=@pubid and artid=@artid
		end

	if (@conf_procname IS NOT NULL) and	not exists (select * from sysmergearticles where
			artid=@artid and pubid<>@pubid) and exists (select * from sysobjects where
			name = @conf_procname and type = 'P')
		begin
			select @owner = user_name(uid) from sysobjects where name=@conf_procname
			select @tmp_procname = QUOTENAME(@owner) + '.' + QUOTENAME(@conf_procname)
			exec ('drop proc ' + @tmp_procname)
			if @@ERROR<>0 return (1)
			update sysmergearticles set ins_conflict_proc = NULL where pubid=@pubid and artid=@artid
		end
	return 0		

GO

exec dbo.sp_MS_marksystemobject sp_MSdroparticleprocs
go

raiserror('Creating procedure sp_MSdroparticletriggers', 0,1)
GO

create procedure sp_MSdroparticletriggers
	(@source_table nvarchar(258))
as
	set nocount on
	declare @instrigger 	sysname
	declare @updtrigger 	sysname
	declare @deltrigger 	sysname
	declare @retcode		int
	declare @owner			sysname
	declare @artid			uniqueidentifier
	declare @guidstr		nvarchar(32)

	-- PARSENAME VARS
	declare  	@UnqualName      sysname  --rightmost name node
	declare  	@QualName1       sysname  
    -- END PARSENAME VARS

    select @UnqualName = PARSENAME(@source_table, 1)
    select @QualName1 = PARSENAME(@source_table, 2)
    if @UnqualName IS NULL
         return 1
	if @QualName1 is not NULL
		select @owner = @QualName1
			else select @owner = 'dbo'
	
	select @artid = artid from sysmergearticles where objid = object_id(@source_table)

	exec @retcode=sp_MSguidtostr @artid, @guidstr out
	if @retcode<>0 or @@ERROR<>0 return (1)

	set @instrigger = @owner + '.ins_' + @guidstr
	set @updtrigger = @owner + '.upd_' + @guidstr
	set @deltrigger = @owner + '.del_' + @guidstr
	
/*	
	select @instrigger = sysobjects.name from sysobjects where 
		ObjectProperty (sysobjects.id, 'ExecIsInsertTrigger') = 1 
		and ObjectProperty (sysobjects.id, 'IsMSShipped') = 1 
		and parent_obj = OBJECT_ID(@source_table) 

	select @updtrigger = sysobjects.name from sysobjects where 
		ObjectProperty (sysobjects.id, 'ExecIsUpdateTrigger') = 1 
		and ObjectProperty (sysobjects.id, 'IsMSShipped') = 1 
		and parent_obj = OBJECT_ID(@source_table) 

	select @deltrigger = sysobjects.name from sysobjects where 
		ObjectProperty (sysobjects.id, 'ExecIsDeleteTrigger') = 1 
		and ObjectProperty (sysobjects.id, 'IsMSShipped') = 1 
		and parent_obj = OBJECT_ID(@source_table) 
*/

	if object_id(@instrigger) is not NULL
		begin
			exec ('drop trigger ' + @instrigger)
			if @@ERROR<>0 return (1)
		end
	if object_id(@updtrigger) is not NULL
		begin
			exec ('drop trigger ' + @updtrigger)
			if @@ERROR<>0 return (1)
		end
	if object_id(@deltrigger) IS NOT NULL
		begin
			exec ('drop trigger ' + @deltrigger)
			if @@ERROR<>0 return (1)
		end

	return 0
GO

exec dbo.sp_MS_marksystemobject sp_MSdroparticletriggers
go
grant execute on dbo.sp_MSdroparticletriggers to public

raiserror('Creating procedure sp_mergesubscription_cleanup', 0,1)
GO

CREATE PROCEDURE sp_mergesubscription_cleanup (
	@publisher		sysname,
	@publisher_db	sysname,
	@publication 	sysname
	) AS
	declare @pubid 				uniqueidentifier
	declare @parentid 			uniqueidentifier
	declare @artid 				uniqueidentifier
	declare @retcode			smallint
	declare @subscription_type  int

	/*
	** if there is nothing to cleanup, then just return.
	*/
	if not exists (select * from sysobjects where name='sysmergesubscriptions')
		return (0)
		
	/* This only gets called after database is enable to subscribe, so sysmergepublications should exist */
	select @pubid = pubid, @parentid = parentid FROM sysmergepublications 
		WHERE name = @publication and UPPER(publisher)=UPPER(@publisher) and publisher_db=@publisher_db

	/* Normal case - nothing to cleanup, just return */
	if @pubid is null
		return (1)

	select @subscription_type = subscription_type from sysmergesubscriptions where pubid=@pubid and subid<>pubid

	/* This procedure is not intended to be used for cleanning-up pull/anonymous subscriptions */
	if @subscription_type > 0
		begin
			raiserror(20091, 16, -1)
			return (1)
		end

	/* Clean up the articles for this publication, and delete the row */
	select @artid = artid FROM sysmergearticles WHERE pubid = @pubid
	while @artid is not null
		begin
		if not exists (select * from sysmergearticles WHERE artid = @artid and pubid <> @pubid)
			begin
				exec @retcode=sp_MSarticlecleanup @pubid, @artid
				if @retcode<>0 or @@ERROR<>0 return (1)
			end
		delete from sysmergearticles where artid = @artid and pubid = @pubid
		set @artid = NULL
		select @artid = artid FROM sysmergearticles WHERE pubid = @pubid
		end
		
	/* Now clean up any traces in other system tables */
	

	delete from MSmerge_genhistory where pubid = @pubid
	delete from MSmerge_replinfo where repid in (select subid from sysmergesubscriptions where pubid = @pubid)

	delete from sysmergesubscriptions where pubid = @pubid
	delete from sysmergepublications where pubid = @pubid
	delete from sysmergeschemachange where pubid = @pubid
GO
exec dbo.sp_MS_marksystemobject sp_mergesubscription_cleanup
go
grant execute on dbo.sp_mergesubscription_cleanup to public

raiserror('Creating procedure sp_subscription_cleanup', 0,1)
GO
CREATE PROCEDURE sp_subscription_cleanup (
	@publisher		sysname,
	@publisher_db	sysname,
	@publication	sysname = NULL,
	@reserved		nvarchar(10) = NULL
)AS

	declare @object_name sysname
	declare @object_type char(2)
	declare @independent_agent bit
	declare @retcode int
	declare @synctran_bit int
    declare @parent_obj int
    declare @object_id int

	select @synctran_bit			= 256

	/*
    ** Security Check
    */

	EXEC @retcode = dbo.sp_MSreplcheck_subscribe
	IF @@ERROR <> 0 or @retcode <> 0
		RETURN(1)

	if @publication = '' OR @publication is NULL
		select @independent_agent = 0
	else
		select @independent_agent = 1

	IF exists (select name from sysobjects where name = 'MSreplication_objects')
	BEGIN
		declare object_cursor CURSOR LOCAL FAST_FORWARD for 
			select DISTINCT object_name, object_type from MSreplication_objects o, MSreplication_subscriptions s
				where (UPPER(s.publisher) = UPPER(@publisher) AND
				  	  s.publisher_db = @publisher_db AND
			  		  (s.publication = @publication or
			  		  s.independent_agent = @independent_agent) and
	  		  		  o.publisher = @publisher and
			  		  o.publisher_db = @publisher_db and
				  	  (o.publication = s.publication or
				  	  	@independent_agent = 0)) or
						@reserved = 'drop_all'

		OPEN object_cursor
    	FETCH object_cursor INTO @object_name, @object_type
 	    WHILE (@@fetch_status <> -1)
    	      BEGIN
        	      IF @object_type = 'T' 
				  begin
					select @parent_obj = NULL
					select @parent_obj = parent_obj, @object_id = id from
						sysobjects where name = @object_name 
					if @parent_obj is not null
					begin
						-- Unmark synctran bit
						update sysobjects set replinfo = replinfo & ~@synctran_bit where 
							id = @parent_obj and
							(replinfo & @synctran_bit) <> 0
						IF @@ERROR <> 0 
							GOTO UNDO
						exec @retcode = dbo.sp_MSdrop_object 
							@object_id = @object_id
						if @retcode <> 0 or @@error <> 0
							goto UNDO
					end
				  end
        	      delete from MSreplication_objects where object_name=@object_name
            	  FETCH object_cursor INTO @object_name, @object_type
         	 END
    	CLOSE object_cursor
    	DEALLOCATE object_cursor
    	
    if not exists (select * from MSreplication_objects) 
    	drop table MSreplication_objects
    	
	END

	IF exists (select name from sysobjects where name = 'MSreplication_subscriptions')
	BEGIN
	delete from MSreplication_subscriptions 
		where (UPPER(publisher) = UPPER(@publisher) AND
			  publisher_db = @publisher_db AND
			  (@independent_agent=0 or publication = @publication))
			  or @reserved = 'drop_all'
 
	END


	IF EXISTS(select * from sysobjects where type='U' and name = 'MSsubscription_properties')
	BEGIN
		DELETE FROM MSsubscription_properties 
		WHERE (UPPER(publisher) = UPPER(@publisher)	AND
		publisher_db  = @publisher_db AND
		publication = @publication) 
		or @reserved = 'drop_all'

		IF @@ERROR <> 0 
			GOTO UNDO

		IF NOT EXISTS (SELECT * FROM MSsubscription_properties)
		BEGIN
			DROP TABLE MSsubscription_properties
			IF @@ERROR <> 0 
				GOTO UNDO
		END
	END
	
    return (0)
            
UNDO:
	return(1)
GO
exec dbo.sp_MS_marksystemobject sp_subscription_cleanup 
go


raiserror('Creating procedure sp_get_distributor', 0,1)
go

-- Called by the UI to find out if the distributor is installed without doing RPC.
CREATE PROCEDURE sp_get_distributor 
AS
    SET NOCOUNT ON

    /*
    ** Declarations.
    */
    DECLARE @distributor sysname
	DECLARE @installed bit
	declare @distdb_installed bit
	declare @is_distpublisher bit
	declare @has_remote_distpublisher bit
 	declare @distbit int

	SELECT @distbit = 16
       
	SELECT @distributor = datasource FROM master..sysservers
		WHERE srvstatus & 8 <> 0

	if @distributor is not null
		select @installed = 1
	else
		select @installed = 0

	if UPPER(@distributor) = UPPER(@@servername)
	begin
		if exists (select * from msdb.dbo.MSdistributiondbs) 
			select @distdb_installed = 1
		else
			select @distdb_installed = 0

		if exists (select * from msdb..MSdistpublishers where UPPER(name) = UPPER(@@servername))
			select @is_distpublisher = 1
		else
			select @is_distpublisher = 0

		if exists (select * from msdb..MSdistpublishers where UPPER(name) <> UPPER(@@servername))
			select @has_remote_distpublisher = 1
		else
			select @has_remote_distpublisher = 0
	end
	else
	begin
		select @distdb_installed = 0
		select @has_remote_distpublisher = 0	
		select @is_distpublisher = 0
	end

	select 'installed' = @installed, 'distribution server' = @distributor,
			'distribution db installed' = @distdb_installed,
			'is distribution publisher' = @is_distpublisher,
			'has remote distribution publisher' = @has_remote_distpublisher
GO

exec dbo.sp_MS_marksystemobject sp_get_distributor
go


-- Called by sp_addrolemember
raiserror('Creating procedure sp_MSrepl_addrolemember', 0,1)
go
CREATE PROCEDURE sp_MSrepl_addrolemember
	@rolename       sysname,
	@membername     sysname
AS
    -- SETUP RUNTIME OPTIONS / DECLARE VARIABLES --
	set	nocount on
	
	return(0)

go		

exec dbo.sp_MS_marksystemobject sp_MSrepl_addrolemember
go

-- Called by sp_droprolemember
raiserror('Creating procedure sp_MSrepl_droprolemember', 0,1)
go
CREATE PROCEDURE sp_MSrepl_droprolemember
	@rolename       sysname,
	@membername     sysname
AS
	set	nocount on
	return(0)
go		

exec dbo.sp_MS_marksystemobject sp_MSrepl_droprolemember
go

raiserror('Creating procedure sp_table_validation', 0,1)
go

create procedure sp_table_validation
@table sysname,					-- table name or sync object name
@expected_rowcount int = NULL OUTPUT,
@expected_checksum numeric = NULL OUTPUT,
@rowcount_only bit = 1,
@owner	sysname = NULL,
@full_or_fast tinyint = 2,		-- full (value 0) does COUNT(*) 
							    -- fast (value 1) uses sysindexes.rows if table (not view); 
								-- conditional fast (VALUE 2) , first tries fast method, but
								-- reverts to full if fast method shows differences.
@shutdown_agent bit = 0, 		-- If 1 will raise error 20578, which will signal replication agent to shutdown
@table_name sysname	= NULL		-- table name of sync object or the table name for output message

as

set nocount on

declare @num_rows int
-- RHS:  original proc by CC used INT.  
-- But INT will not be acceptable longer term - table may have more than 2bil rows
-- For now, leave it at INT and come back and improve this later.

declare @checksum numeric
declare @checksum_string varchar(100)
declare @expected_checksum_string varchar(100)
declare @width int
declare @qualified_table_name nvarchar(262)  -- two names plus []'s and a .
declare @temp_table_used bit
declare @retstatus int
declare @failed_fast tinyint
declare @min_indid int
declare @asked_for_exp_checksum tinyint
declare @asked_for_exp_rows tinyint

-- declare @debug tinyint   -- Temporary.   Take this out before beta 3 (or when TSQL debugger comes online)


SET @retstatus=0	-- initialize to SUCCESS
SET @failed_fast=0
-- SET @debug=0


if (@expected_checksum IS NULL AND @rowcount_only = 0 )  -- Wants an expected checksum value
	SET @asked_for_exp_checksum=1
ELSE
	SET @asked_for_exp_checksum=0


if (@expected_rowcount IS NULL)  -- Wants an expected checksum value
	SET @asked_for_exp_rows=1
ELSE
	SET @asked_for_exp_rows=0


-- RHS:  Should go back and do better parameter checking here
-- Some states do not make sense.  For example,  it does not make sense to ask for conditional
-- fast row count checking, yet not provide an expected value.  If this is done, provide a warning
-- message and use fast checking method.
if (@full_or_fast = 2 AND @expected_rowcount IS NULL)
	BEGIN
	-- Msg 20559,'Conditional Fast Rowcount method requested without specifying an expected count.  Fast method will be used.'
	raiserror (20559, 10, -1)
	SET @full_or_fast = 1
	END

-- Another state that doesn't make sense is to pass an expected checksum value, yet
-- ask for rowcount only validation
if (@expected_checksum IS NOT NULL AND @rowcount_only > 0)
	BEGIN
	-- Msg 20560,'An expected checksum value was passed, but checksums will not be compared because Rowcount only checking was requested.'
	raiserror (20560, 10, -1)
	SET @expected_checksum = NULL
	END

	
if @owner is null
begin
	if left(ltrim(rtrim(@table)), 1) <> '[' or right(ltrim(rtrim(@table)), 1) <> ']'
		set @qualified_table_name = '[' + @table + ']'
	else
		set @qualified_table_name = @table
end
else
begin
	if left(ltrim(rtrim(@table)), 1) <> '[' or right(ltrim(rtrim(@table)), 1) <> ']'
		set @qualified_table_name = '[' + @owner + '].[' + @table + ']'
	else
		set @qualified_table_name = '[' + @owner + '].' + @table
end


-- If the object is a table (not view) and fast checking (1) requested,
-- then get rowcount from sysindexes, rather than scanning
IF (SELECT @full_or_fast) > 0    -- IF Fast row checking asked for
	AND 
   (SELECT OBJECTPROPERTY(OBJECT_ID(@qualified_table_name),'IsTable')) > 0  -- Must be a table, not a view

	BEGIN
		-- Do the fast rowcount method
		-- Temporarily put a SHARE lock on table to ensure no simultaneous updates going on
		-- Minimizes chances of getting an out of date value from sysindexes.   True that
		-- it reduces concurrency, but if the fast method doesnt work the user will very likely
		-- go do the full method, which will be much more costly.   Better I think to take a little more cost here
		-- and hopefully get a good number.   The @foo variable is used so that its an
		-- assignment and doesn't make another result set get returned.

		-- DEBUG
		-- if @debug=1 PRINT "Querying for fast rowcount"

		BEGIN TRAN
		EXEC ('DECLARE @foo int SELECT @foo=1 FROM ' + @qualified_table_name + ' (TABLOCK HOLDLOCK) WHERE 1=2')
		SELECT @num_rows=rows,@min_indid=indid FROM sysindexes WHERE id=OBJECT_ID(@qualified_table_name)and indid < 2
		COMMIT TRAN
	END

ELSE 
	BEGIN
	-- if @debug=1 PRINT "setting variable to use full row count"
	SET @full_or_fast = 0   -- Full checking will be used, regardless of whether it was requested
	END

--	set the output name if not set
	if (@table_name IS NULL)
		SELECT @table_name = @table

-- If fast row checking was used, and request for rowcount check only, we're done.
if (@full_or_fast = 1  AND  @rowcount_only > 0) 
	BEGIN
	-- if @debug=1 PRINT "fast rowcount only requested & done - going to rowcount msg"
	GOTO ROWCOUNT_MSG
	END

-- If conditional fast row checking was used, and request for rowcount check only, 
-- we're also done IFF rows and expected rows match.
if (@full_or_fast = 2  AND  @rowcount_only > 0 
	AND @expected_rowcount IS NOT NULL AND @expected_rowcount=@num_rows)
	BEGIN
		-- Fast checking was actually used.
		-- if @debug=1 PRINT "conditional fast rowcount requested & passed - going to rowcount msg"
		SET @full_or_fast = 1
		GOTO ROWCOUNT_MSG
	END


-- If we're still here we are doing full row checking at a minimum, and will need the temp table
IF (SELECT ISNULL(OBJECT_ID('tempdb..#tab_validt1'),0)) = 0    -- Table Does Not exist
	CREATE TABLE #tab_validt1 (tmp_rows int NULL, tmp_checksum numeric NULL)
ELSE -- table already exists 
	TRUNCATE TABLE #tab_validt1

-- If we are only doing row checking, we'll do it here.  If we will do both row checking 
-- and checksum, then do them together so as to not scan table twice.
if @rowcount_only = 1
	BEGIN   -- Must do full count(*) checking but not checksums
	if @full_or_fast=2   
		-- if we are here with conditional check (2) requested, it is because
		-- a conditional was possible, but it failed.  We wiil later alert user of this.
		BEGIN 
		SET @full_or_fast=0
		SET @failed_fast=1
		END
	
	insert into #tab_validt1 (tmp_rows,tmp_checksum) 
		exec ('select count(*), NULL from ' +	@qualified_table_name + ' (TABLOCK HOLDLOCK)')

	-- Get row count value
	select  TOP 1 @num_rows = tmp_rows from #tab_validt1   -- Should only be one row
	-- if @debug=1 SELECT 'The TEMP TABLE HAS THIS MANY ROWS',count(*) from #tab_validt1 
	
	-- IF there were no rows from above, the table was empty so use ZERO.
	IF @num_rows IS NULL
		SELECT @num_rows=0

	-- Done with the temp table
	DROP TABLE #tab_validt1
	
	IF @expected_rowcount IS NULL
		BEGIN
		SET @expected_rowcount = @num_rows
		END
	GOTO ROWCOUNT_MSG
	END -- Done with full row count only

ELSE  -- Doing checksums in addition to ROWCOUNT
	BEGIN	-- DO checksum and rowcount in same pass thru the table
	insert into #tab_validt1 (tmp_rows,tmp_checksum)
		exec ('select count(*), sum (convert(numeric, getchecksum(NULL,1))) from ' +	@qualified_table_name + ' (TABLOCK HOLDLOCK)')

	-- Get the checksum & rowcount values
	select TOP 1 @checksum = tmp_checksum, @num_rows= tmp_rows from #tab_validt1

	-- IF there were no rows from above, the table was empty so use ZERO.
	IF @checksum IS NULL or @num_rows IS NULL
		SELECT @checksum=isnull(@checksum,0),@num_rows=isnull(@checksum,0)

	-- Done with the temp table
	DROP TABLE #tab_validt1
	
	IF @expected_rowcount IS NULL  -- Just getting value - no expected value yet.
		SET @expected_rowcount = @num_rows
	
	-- Validate checksum
	IF @expected_checksum is null		-- Just getting value - no expected value yet.
		set @expected_checksum = @checksum
	else
		-- Raise error if checksums OR rowcounts do not match
		if @checksum <> @expected_checksum OR @num_rows <> @expected_rowcount
			begin
			-- Checksum failed.
			set @checksum_string = convert(varchar(21), @checksum)
			set @expected_checksum_string = convert(varchar(21), @expected_checksum)
			-- Msg 20525: Table ''%s'' is out of synchronization. Rowcounts (actual: %d, expected %d).  Checksum difference (actual: %s, expected: %s).'
			raiserror (20525, 10, -1, @table, @num_rows, @expected_rowcount, @checksum_string, @expected_checksum_string)
			SET @retstatus=1
			END
		else
		BEGIN
		-- Row count and checksum validation passed.
		-- 
		if @asked_for_exp_checksum=0 -- Only give message if not generating the expected value
			raiserror (20527, 10, -1, @table,@num_rows)
		END
	-- Done with checksum and rowcount scan.
	END
-- We did checksum method, and so are done and skip over the rowcount only messages.
GOTO ALL_DONE

ROWCOUNT_MSG:
-- Raise error if rows counts do not match
	IF @expected_rowcount IS NULL  -- just return the found value
		SET @expected_rowcount=@num_rows
	ELSE
		IF @num_rows <> @expected_rowcount
		begin
	   
			-- Msg 20524:  'Table ''%s'' may be out of synchronization. Row count difference encountered (actual: %d, expected: %d). Row count method %d used.  (0=Full  1=Fast)', NULL)
			raiserror (20524, 10, -1, @table_name, @num_rows, @expected_rowcount, @full_or_fast )
			SET @retstatus=1
		end
		ELSE	-- Row count validation passed. 
		begin

			if @asked_for_exp_rows=0 -- Only give message if not generating the expected value
		      	-- Msg 20526:  'Table ''%s'' passed row count (%d) validation.  Row count method %d used. (0=Full  1=Fast)''
			raiserror (20526, 10, -1, @table_name, @num_rows, @full_or_fast)
			
			if @failed_fast=1
			BEGIN
			-- if we had to revert to FULL on a CONDITIONAL FAST, Make that known too.
			-- And Update usage to fix the problem
			-- Msg 20558: 'Table ''%s'' passed full row count validation after failing the fast check.  DBCC UPDATEUSAGE will be automatically initiated.'
			raiserror (20558, 10, -1, @table_name)
			DBCC UPDATEUSAGE (0,@qualified_table_name,@min_indid) WITH COUNT_ROWS, NO_INFOMSGS
			END
		end

ALL_DONE:

-- Give nice message if only generating the expected value:

-- Msg for rows and checksum:
if @asked_for_exp_checksum=1 and @asked_for_exp_rows=1 -- Only give message if generating the expected value
       BEGIN
       set @expected_checksum_string = convert(varchar(21), @expected_checksum)
       -- Msg 20579:'Generated expected rowcount value of %d and expected checksum value of %s for %s .'
       raiserror (20579, 10, -1, @expected_rowcount,@expected_checksum_string,@table_name)
       END
       
ELSE
	BEGIN
		if @asked_for_exp_checksum=0 and @asked_for_exp_rows=1
		-- Msg 20561:'Generated expected rowcount value of %d for %s .', 1033)
		raiserror (20561, 10, -1, @expected_rowcount, @table_name)
	END
        

-- Raise error that will shutdown replication agents
if @shutdown_agent = 1
	--Msg 20578: 'Shutdown replication agent request.'
	raiserror (20578, 10, -1)
	
return @retstatus
go

exec dbo.sp_MS_marksystemobject sp_table_validation
go

/* Create  sp_removedbreplication */
raiserror('Creating procedure sp_removedbreplication', 0,1)
GO

/* Permission to sysadmin */
CREATE PROCEDURE sp_removedbreplication (
	  @dbname	 sysname
	) AS

    SET NOCOUNT ON

    /*
    ** Declarations.
    */

	DECLARE @retcode int
	DECLARE @proc nvarchar(255)
	DECLARE @optbit int
	DECLARE @restoreoverride int
	/*
	** Initialization
	*/


	/*
	** Support override of replication remove on attach and restore
	*/

	SELECT @restoreoverride = 0 -- assume normal remove behavior
	SELECT @proc = 'master.dbo.xp_regread '
	EXECUTE @retcode = @proc	'HKEY_LOCAL_MACHINE', 
								'SOFTWARE\Microsoft\MSSQLServer\Replication',
								'RestoreOverride',
								@param = @restoreoverride OUTPUT,
								@no_output = 'no_output'

	IF ( @@error = 0 ) and ( @retcode = 0 )
	BEGIN
		-- ReplRestoreOverride = 1 = user elects to take no cleanup on restore or attach
		IF ( ISNULL( @restoreoverride, 0 ) = 1 )
			RETURN(0)
	END

	/*
	** Parameter check
	** @dbname
	*/
	IF NOT EXISTS (SELECT * FROM master.dbo.sysdatabases WHERE
		name = @dbname)
	BEGIN
		RAISERROR(15010, 16, -1, @dbname)
		RETURN(1)
	END

	
	SELECT @proc = quotename(@dbname) + '.dbo.sp_MSremovedbreplication'
	
	EXEC @retcode = @proc 
	IF @@ERROR <> 0 or @retcode <> 0
	BEGIN
		return (1)
	END

	-- Clear tran bit
	SELECT @optbit = 1
	IF EXISTS (SELECT * FROM master..sysdatabases
		WHERE name = @dbname
		AND (category & @optbit) <> 0)
	begin
		/*
		** Toggle the category bit in master..sysdatabases
		*/
		UPDATE master..sysdatabases SET category = category & ~@optbit
    			WHERE name = @dbname
		IF @@ERROR <> 0 
		BEGIN
			return (1)
		END
	end

	-- Clear merge bit
	SELECT @optbit = 4
	IF EXISTS (SELECT * FROM master..sysdatabases
		WHERE name = @dbname
		AND (category & @optbit) <> 0)
	begin
		/*
		** Toggle the category bit in master..sysdatabases
		*/
		UPDATE master..sysdatabases SET category = category & ~@optbit
    			WHERE name = @dbname
		IF @@ERROR <> 0 
		BEGIN
			return (1)
		END
	end

	/* 
	 * Bug 47732 - cannot checkpoint in attach or restore
	 * CHECKPOINT
	 * IF @@ERROR <> 0 
	 * BEGIN
	 * 	return (1)
	 * END
	*/
GO
 
exec dbo.sp_MS_marksystemobject sp_removedbreplication
go
 
raiserror('Creating procedure sp_removesrvreplication', 0,1)
GO

create procedure sp_removesrvreplication
as
begin
/* 
 * unmark replication bits for all servers, databases; used by setup in vupgrade 
 * assumes override is on; db in single user mode
 * no need to check rowcounts affected by updates, may not be any repl dbs
 * failure label avoids repetition of errs if not in single user mode
*/

	set nocount on 

	-- server bits
	declare @srv_distbit int
	declare @srv_pubbit int
	declare @srv_subbit int
	declare @srv_dsnbit int

	select @srv_distbit = 8, @srv_pubbit = 16, @srv_subbit = 4, @srv_dsnbit = 32 -- dsn subscriber

	-- db bits
	declare @db_tranbit int
	declare @db_mergbit int
	declare @db_distbit int

	select @db_tranbit = 1, @db_mergbit = 4, @db_distbit = 16

	-- setup attach overrides removedb option
	declare @dbname sysname

	declare cur_db CURSOR LOCAL FAST_FORWARD for 
		select name from master..sysdatabases where name <> N'master'
		for read only
	open cur_db
	fetch cur_db into @dbname
	while ( @@fetch_status <> -1 )
	begin
		exec dbo.sp_removedbreplication @dbname
		-- clean up system tables
		exec ( @dbname + '.dbo.sp_MSdrop_pub_tables' )
		exec ( @dbname + '.dbo.sp_MSdrop_mergesystables' )
		fetch next from cur_db into @dbname
	end
	close cur_db
	deallocate cur_db

	-- unmark db bits
	-- select name, category from sysdatabases where category & @tranbit = @tranbit 
	update master..sysdatabases set category = category & ~@db_tranbit where category & @db_tranbit = @db_tranbit
	if @@ERROR <> 0
		goto fail

	update master..sysdatabases set category = category & ~@db_mergbit where category & @db_mergbit = @db_mergbit
	if @@ERROR <> 0
		goto fail

	-- clean up old dist db bit
	update master..sysdatabases set category = category & ~@db_distbit where category & @db_distbit = @db_distbit
	if @@ERROR <> 0
		goto fail

	-- unmark srv bits (srvstatus = @dsnbit no longer used by replication subscribers but by server )
	-- select name, srvstatus from sysservers where srvstatus & @srv_distbit = @srv_distbit
	update master..sysservers set srvstatus = srvstatus & ~@srv_subbit where srvstatus & @srv_subbit = @srv_subbit
	if @@ERROR <> 0
		goto fail

	update master..sysservers set srvstatus = srvstatus & ~@srv_pubbit where srvstatus & @srv_pubbit = @srv_pubbit
	if @@ERROR <> 0
		goto fail

	update master..sysservers set srvstatus = srvstatus & ~@srv_distbit where srvstatus & @srv_distbit = @srv_distbit
	if @@ERROR <> 0
		goto fail

	return (0)

fail:
-- ad hoc updates not allowed and not single user
return (1)

end
go

exec dbo.sp_MS_marksystemobject sp_removesrvreplication
go

raiserror('Creating procedure sp_MSremovedbreplication', 0,1)
GO

CREATE PROCEDURE sp_MSremovedbreplication
	AS

    SET NOCOUNT ON

    /*
    ** Declarations.
    */

	DECLARE @retcode int

	if exists (select * from sysobjects where name = 'sysarticles')
	-- clean up transactional 
	begin
		if not exists (select * from master..MSreplication_options
			where optname = 'transactional')
		begin
			RAISERROR(21027, 16, -1, 'transactional')
			return(1)
		end
	
		
		EXEC @retcode = dbo.sp_MSpublishdb @value = 'false',
			@ignore_distributor = 1
		IF @@ERROR <> 0 or @retcode <> 0
		BEGIN
			return (1)
		END
	end

	if exists (select * from sysobjects where name = 'sysmergearticles')
	-- clean up merge
	-- can not use sp_MSmergepublishdb or sp_dropmergepullsubscriptions
	-- since they depend on serverid and dbname
	begin
		declare @pubid uniqueidentifier
		declare @artid uniqueidentifier
		declare hC CURSOR LOCAL FAST_FORWARD FOR select DISTINCT pubid, artid FROM 
			sysmergearticles
		FOR READ ONLY       

        OPEN hC
        FETCH hC INTO @pubid, @artid
        WHILE (@@fetch_status <> -1)
		begin

			EXEC @retcode = dbo.sp_MSarticlecleanup
				@pubid, @artid
			IF @@ERROR <> 0 or @retcode <> 0
			BEGIN
				return (1)
			end
			FETCH hC INTO @pubid, @artid
		end

        execute @retcode = dbo.sp_MSdrop_mergesystables
        if @@ERROR <> 0 or @retcode <> 0
        begin
                return (1)
        end
	end


	if exists (select * from sysobjects where name = 'MSreplication_subscriptions')
	-- clean up tran sub
	begin
		-- drop pull subscription
		EXEC @retcode = dbo.sp_droppullsubscription
			@publisher = N'all', 
			@publisher_db = N'all', 
			@publication = N'all'
		IF @@ERROR <> 0 or @retcode <> 0
		BEGIN
			return (1)
		END

	    -- drop push subscription
		EXEC @retcode = dbo.sp_subscription_cleanup
			@publisher = N'all', 
			@publisher_db = N'all', 
			@publication = N'all',
			@reserved = 'drop_all'
		IF @@ERROR <> 0 or @retcode <> 0
		BEGIN
			return (1)
		END
	end
	
GO

exec dbo.sp_MS_marksystemobject sp_MSremovedbreplication
go

raiserror('Creating procedure sp_vupgrade_subscription_databases', 0,1)
GO
create procedure sp_vupgrade_subscription_databases
as
	declare @dbname sysname

	declare current_db CURSOR LOCAL FAST_FORWARD for 
		select quotename(name) from master..sysdatabases 
		for read only

	-- Note: dbname is quoted!
	open current_db
	fetch current_db into @dbname
	while ( @@fetch_status <> -1 )
	begin
		exec ('use '+ @dbname + ' exec dbo.sp_vupgrade_MSsubscription_properties')
		exec ('use '+ @dbname + ' exec dbo.sp_vupgrade_mergetables')

		fetch next from current_db into @dbname
	end
	close current_db
	deallocate current_db
go

raiserror('Creating procedure sp_vupgrade_mergetables', 0,1)
GO
create procedure sp_vupgrade_mergetables
as
	declare @artnick int
	declare @objid  int
	declare @ccols int
	declare @goodlen int
	declare @col_track int
	declare @article sysname
	declare @pubid uniqueidentifier
	declare @pubname sysname
    declare @qualified_name         nvarchar(257)
    declare @source_owner           sysname
    declare @source_object			sysname
	
	if (exists (select * from sysobjects where name = 'sysmergearticles'))
		begin
		-- A column has been added to the sysmergearticles table
		if not exists (select * from syscolumns where id = object_id('sysmergearticles') and
							name = 'gen_cur')
			begin
			alter table sysmergearticles add gen_cur int null
			if @@ERROR <> 0
				return 1
			end
		-- an index has been added on genhistory(guidlocal)
		if not exists (select * from sysindexes where name = 'nc2MSmerge_genhistory')
			begin
			create  index nc2MSmerge_genhistory on MSmerge_genhistory(guidlocal) 
			if @@ERROR <> 0
				return 1
			end
		-- previous builds had a bug that caused truncated colv metadata
		select @artnick = min(nickname) from sysmergearticles
		while @artnick is not null
			begin
			-- find base table to compute number of columns
			select @objid = objid, @col_track = column_tracking, @article = name
				from sysmergearticles where nickname = @artnick
				
			select @pubname = min(name) from sysmergepublications where pubid in
				(select pubid from sysmergearticles where nickname = @artnick)
			while @pubname is not null
				begin
				-- remake the articles procs
				exec sp_MSsetartprocs @pubname, @article, 1
				select @pubname = min(name) from sysmergepublications where name > @pubname and pubid in
					(select pubid from sysmergearticles where nickname = @artnick)
				end

			-- regenerate the triggers
            select @source_owner = user_name(uid), @source_object = name from sysobjects where id = @objid
		    select @qualified_name = QUOTENAME(@source_owner) + '.' + QUOTENAME(@source_object)
			exec sp_MSaddmergetriggers @qualified_name, @col_track

			if @col_track = 1
				begin
				select @ccols = count(*) from syscolumns where id = @objid

				-- compute expected length of colv1
				set @goodlen = 8 * @ccols
				if @goodlen > 2040 set @goodlen = 2040

				-- delete metadata that has truncated colv
				delete from MSmerge_contents where tablenick = @artnick and datalength(colv1) < @goodlen
				end
				
			-- find next article
			select @artnick = min(nickname) from sysmergearticles where nickname > @artnick
			end

		-- Loop over publications and recreate the views
		select @pubname = min(name) from sysmergepublications where UPPER(publisher)=UPPER(@@SERVERNAME) and publisher_db=db_name()

		while @pubname is not null
			begin
			-- remake the publication views
			exec sp_MSpublicationview @pubname, 1
			select @pubname = min(name) from sysmergepublications where name > @pubname and UPPER(publisher)=UPPER(@@SERVERNAME) and publisher_db=db_name()

			end
		end
GO

raiserror('Creating procedure sp_vupgrade_MSsubscription_properties', 0,1)
GO
create procedure sp_vupgrade_MSsubscription_properties
as
	-- Add FTP properties to MSsubscription_properties.  These where added after B3 of 7.0 
	-- and before RTM.
	IF EXISTS (SELECT * FROM sysobjects WHERE name = 'MSsubscription_properties'
		and type = 'U')
	begin
		if not exists (select * from syscolumns where name = 'ftp_address' and
			id = OBJECT_ID('MSsubscription_properties'))
		begin
			alter table MSsubscription_properties ADD ftp_address sysname NULL
			if @@ERROR <> 0
				return 1
		end

		if not exists (select * from syscolumns where name = 'ftp_port' and
			id = OBJECT_ID('MSsubscription_properties'))
		begin
			alter table MSsubscription_properties ADD ftp_port int NULL
			if @@ERROR <> 0
				return 1
		end

		if not exists (select * from syscolumns where name = 'ftp_login' and
			id = OBJECT_ID('MSsubscription_properties'))
		begin
			alter table MSsubscription_properties ADD ftp_login sysname NULL
			if @@ERROR <> 0
				return 1
		end

		if not exists (select * from syscolumns where name = 'ftp_password' and
			id = OBJECT_ID('MSsubscription_properties'))
		begin
			alter table MSsubscription_properties ADD ftp_password sysname NULL
			if @@ERROR <> 0
				return 1
		end

	end
go

raiserror('Creating procedure sp_vupgrade_replication', 0,1)
GO

create procedure sp_vupgrade_replication ( @login sysname = N'sa', @password sysname = N'', @ver_old int = 517, @force_remove tinyint = 0 )
as
begin
/* 
 * Stub to handle possible need to modify or supplement replication metadata during setup 
 * initiated version upgrade from Beta 3 (and subsequent builds) to RTM. Any schema changes
 * to replication system tables may require modifications here to maintain upgrade path.
 * 
 * If server is a distributor, run new instdist.sql against all distribution dbs.
 * If version upgraded from is pre-Beta 3 OR @force_remove is true, do hard strip of replication.
 *
 * This proc gets called by setup at the end of an install over an existing version. 
*/

	set nocount on 

	declare @dbname sysname
	declare @install_path nvarchar(255)
	declare @osql_cmd nvarchar(512)
	declare @osql_for_nt int
	declare @retcode int
    declare @platform_nt binary
    
	-- db bits
	declare @db_distbit int

	select @db_distbit = 16

	-- version check
	declare @ver_min 			int
	declare @ver_retention		int

    select @platform_nt = 0x1
	select @ver_min= 517
	select @ver_retention = 576 --build # on 9/17

	if ( @ver_old < @ver_min ) or ( @force_remove = 1 )
		exec dbo.sp_removesrvreplication
	else
	begin

		-- always need to run instdist.sql to update distribution databases on a distributor
		-- setup must restart in non-single user mode so we can shell out to run instdist.sql scripts

		if exists( select * from master..sysdatabases where category & @db_distbit = @db_distbit )
		begin

			-- get install_path
			exec @retcode = master.dbo.xp_regread 'HKEY_LOCAL_MACHINE',
					  'SOFTWARE\Microsoft\MSSQLServer\Setup',
					  'SQLPath',
					@param = @install_path OUTPUT

			if ( @retcode <> 0 ) or ( @install_path is null ) or ( @install_path = N'' )
			begin
				return(1)
			end
			
			-- Set the flag for platform
			if (( platform() & @platform_nt = @platform_nt ))
				select @osql_for_nt = 1
			else
				select @osql_for_nt = 0

			declare cur_distdb CURSOR LOCAL FAST_FORWARD for 
				select name from master..sysdatabases 
					where category & @db_distbit = @db_distbit
				for read only
			
			open cur_distdb
			fetch cur_distdb into @dbname
			while ( @@fetch_status <> -1 )
			begin

				if (@osql_for_nt = 1)
					select @osql_cmd = '" '
				else
					select @osql_cmd = ' '
					 
				select @osql_cmd = @osql_cmd + '"' + @install_path + '\binn\osql" -U' + isnull(@login, N'sa') + ' -P' + isnull(@password, N'') + ' -S' + @@SERVERNAME
				select @osql_cmd = @osql_cmd + ' -l30 -t30 '
				select @osql_cmd = @osql_cmd + ' -b ' + ' -d' + @dbname
				select @osql_cmd = @osql_cmd +	' -i' + '"' + @install_path + '\install\instdist.sql"' + 
												' -o' + '"' + @install_path + '\install\instdist.out"'			

				if (@osql_for_nt = 1)
					select @osql_cmd = @osql_cmd + ' "'

	 			exec @retcode = master..xp_cmdshell @osql_cmd
				if @retcode <> 0 or @@error <> 0
				begin
					raiserror (14113, 16, -1, @osql_cmd, 'instdist.out')
				end

				fetch next from cur_distdb into @dbname
			end
			close cur_distdb
			deallocate cur_distdb

			-- Upgrade replication settings/tables in MSDB database
			-- ONLY FOR DISTRIBUTORS
			exec @retcode = dbo.sp_vupgrade_replmsdb
			if @retcode <> 0 or @@error <> 0
			        return (1)

		end

		-- Note: place calls to procs for any schema or metadata changes required in else block here

	   		exec @retcode = dbo.sp_vupgrade_publisher 
	   			@ver_old = @ver_old, 
	   			@ver_retention = @ver_retention
	    	if @retcode<>0 or @@error<>0
	    		return (1)
	
		-- Update subscription database schema
		exec @retcode = dbo.sp_vupgrade_subscription_databases
		if @retcode <> 0 or @@error <> 0
			return (1)

	end

	return (0)

end
go

exec dbo.sp_MS_marksystemobject sp_vupgrade_replication
go

raiserror('Creating procedure sp_vupgrade_publisher', 0,1)
go

create procedure sp_vupgrade_publisher 
@ver_old int,
@ver_retention int
as
SET NOCOUNT ON

declare @proc_name			nvarchar(200)
declare @publication		sysname
declare @upgraded			bit 
declare @retcode 			int
declare @publisher_db		sysname
declare @agentname			sysname
/*
** Security Check
*/
EXEC @retcode = dbo.sp_MSreplcheck_publish
	IF @@ERROR <> 0 or @retcode <> 0
		return (1)
	/*
	** Get distribution server information for remote RPC call.
	*/

	-- Get expired subscription cleanup agent name
    set @agentname = formatmessage(20569)  
	
	UPDATE msdb.dbo.sysjobs
	SET name = @agentname
	FROM msdb.dbo.sysjobs, msdb.dbo.sysjobsteps as s
	WHERE msdb.dbo.sysjobs.job_id = s.job_id
	AND 
	( UPPER(s.command) = UPPER(N'EXEC sp_MScleanup_subscription') 
	OR UPPER(s.command) = UPPER(N'EXEC dbo.sp_MScleanup_subscription') )

	UPDATE msdb.dbo.sysjobsteps 
	SET command = N'EXEC dbo.sp_expired_subscription_cleanup' 
	WHERE UPPER(command) = UPPER(N'EXEC sp_MScleanup_subscription')
	OR UPPER(command) = UPPER(N'EXEC dbo.sp_MScleanup_subscription')
		
DECLARE DC CURSOR LOCAL FAST_FORWARD for select DISTINCT name from master..sysdatabases 
--  Merge schema change should happen on all dbs since the sub db is not marked for publish.
--	where ((category & 4) = 4) or ((category & 1) = 1)
	for read only
open DC
fetch DC into @publisher_db
WHILE (@@fetch_status <> -1)
	BEGIN
		select @proc_name = @publisher_db + '.dbo.sp_vupgrade_publisherdb'
		exec @retcode = @proc_name 
			@ver_old = @ver_old,
			@ver_retention = @ver_retention
		if @retcode<>0 or @@ERROR<>0
			begin
				close DC
				deallocate DC
				return (1)
			end
		fetch DC into @publisher_db
	END
close DC
deallocate DC
GO

exec dbo.sp_MS_marksystemobject sp_vupgrade_publisher
go
grant execute on dbo.sp_vupgrade_publisher to public
go

raiserror('Creating procedure sp_vupgrade_publisherdb', 0,1)
go
create procedure sp_vupgrade_publisherdb 
@ver_old int,
@ver_retention int
AS

declare @default_name sysname 

if exists (select name from sysobjects where name='syspublications')
begin
	if @ver_old < @ver_retention
	begin
		update syspublications set retention = 72 
		if @@error<>0
			return (1)
	end

	-- drop default_access column
	if exists (select * from syscolumns where id = object_id('syspublications') and
		name = 'default_access')
	begin
		alter table syspublications drop column default_access
	end 
end

if exists (select name from sysobjects where name='sysmergepublications')
begin
	alter table sysmergearticles alter column resolver_info nvarchar(255) NULL
	if @@ERROR <> 0
		return 1

	if @ver_old < @ver_retention
	begin
		update sysmergepublications set retention = 60 
		if @@error<>0
			return (1)
	end

	-- drop default_access column
	if exists (select * from syscolumns where id = object_id('sysmergepublications') and
		name = 'default_access')
	begin
        -- Get the name of the default associated with default_access and then 
        -- drop it 
        select @default_name = null
        select @default_name = object_name(constid) from sysconstraints    
        where id = object_id('sysmergepublications') and 
              col_name(id, colid) = N'default_access'
        if @default_name is not null
        begin
            -- Drop the default
            exec (N'alter table sysmergepublications drop constraint ' + @default_name) 
        end    

		alter table sysmergepublications drop column default_access
	end 
end

GO
exec dbo.sp_MS_marksystemobject sp_vupgrade_publisherdb
go
grant execute on dbo.sp_vupgrade_publisherdb to public
go

raiserror('Creating procedure sp_vupgrade_replmsdb', 0,1)
go
create procedure sp_vupgrade_replmsdb 
as
/*
** used to upgrade replication settings/tables in MSDB database
*/
begin

	declare @retcode int
	declare @profile_id int
	
	-- Drop and regenerate agent parameters and associated values 
	-- from system profiles.
	--
	select @profile_id = 1
	while (@profile_id < 8)
	  begin

		exec @retcode = dbo.sp_drop_agent_parameter @profile_id
	    if (@retcode = 1)
	        return (1)

		exec @retcode = dbo.sp_generate_agent_parameter @profile_id
	    if (@retcode = 1)
	        return (1)

		select @profile_id = @profile_id + 1

	  end
    /* create MSdatatype_mappings table */
    IF NOT EXISTS (SELECT * FROM msdb..sysobjects WHERE name = 'MSdatatype_mappings' 
        and xtype = 'U')
    begin

        create table msdb.dbo.MSdatatype_mappings 
        (
        dbms_name           sysname NOT NULL,
        sql_type            sysname NOT NULL,
        dest_type           sysname NOT NULL,
        dest_prec           int     NOT NULL,
        dest_create_params  int     NOT NULL,
        dest_nullable       bit     NOT NULL
        )

        exec dbo.sp_add_datatype_mapping 'MS Jet', 'binary' , 'binary', 255, 4, 1
        exec dbo.sp_add_datatype_mapping 'MS Jet', 'varbinary' , 'varbinary', 255, 4, 1
        exec dbo.sp_add_datatype_mapping 'MS Jet', 'binary' , 'image', 1073741824, 0, 1
        exec dbo.sp_add_datatype_mapping 'MS Jet', 'varbinary' , 'image', 1073741824, 0, 1
        exec dbo.sp_add_datatype_mapping 'MS Jet', 'varchar' , 'varchar', 255, 4, 1
        exec dbo.sp_add_datatype_mapping 'MS Jet', 'varchar' , 'longtext', 1073741824, 0, 1
        exec dbo.sp_add_datatype_mapping 'MS Jet', 'nchar' , 'nchar', 255, 4, 1
        exec dbo.sp_add_datatype_mapping 'MS Jet', 'nchar' , 'longtext', 1073741824, 0, 1
        exec dbo.sp_add_datatype_mapping 'MS Jet', 'char' , 'char', 255, 4, 1
        exec dbo.sp_add_datatype_mapping 'MS Jet', 'char' , 'longtext', 1073741824, 0, 1
        exec dbo.sp_add_datatype_mapping 'MS Jet', 'nvarchar' , 'nchar varying', 255, 4, 1
        exec dbo.sp_add_datatype_mapping 'MS Jet', 'nvarchar' , 'longtext', 1073741824, 0, 1
        exec dbo.sp_add_datatype_mapping 'MS Jet', 'datetime' , 'datetime', 255, 0, 1
        exec dbo.sp_add_datatype_mapping 'MS Jet', 'smalldatetime' , 'datetime', 255, 0, 1
        exec dbo.sp_add_datatype_mapping 'MS Jet', 'decimal' , 'decimal', 255, 3, 1
        exec dbo.sp_add_datatype_mapping 'MS Jet', 'numeric' , 'decimal', 255, 3, 1
        exec dbo.sp_add_datatype_mapping 'MS Jet', 'float' , 'float', 255, 0, 1
        exec dbo.sp_add_datatype_mapping 'MS Jet', 'real' , 'real', 255, 0, 1
        exec dbo.sp_add_datatype_mapping 'MS Jet', 'int' , 'int', 255, 0, 1
        exec dbo.sp_add_datatype_mapping 'MS Jet', 'smallint' , 'smallint', 255, 0, 1
        exec dbo.sp_add_datatype_mapping 'MS Jet', 'tinyint' , 'byte', 255, 0, 1
        exec dbo.sp_add_datatype_mapping 'MS Jet', 'money' , 'currency', 255, 0, 1
        exec dbo.sp_add_datatype_mapping 'MS Jet', 'smallmoney' , 'currency', 255, 0, 1
        exec dbo.sp_add_datatype_mapping 'MS Jet', 'bit' , 'bit', 255, 0, 1
        exec dbo.sp_add_datatype_mapping 'MS Jet', 'sysname' , 'nchar varying', 255, 4, 1
        exec dbo.sp_add_datatype_mapping 'MS Jet', 'timestamp' , 'binary', 255, 4, 1
        exec dbo.sp_add_datatype_mapping 'MS Jet', 'uniqueidentifier' , 'guid', 255, 0, 1
        exec dbo.sp_add_datatype_mapping 'MS Jet', 'text' , 'longtext', 1073741824, 0, 1
        exec dbo.sp_add_datatype_mapping 'MS Jet', 'ntext' , 'longtext', 1073741824, 0, 1
        exec dbo.sp_add_datatype_mapping 'MS Jet', 'image' , 'image', 1073741824, 0, 1

        exec dbo.sp_add_datatype_mapping 'Oracle', 'binary' , 'raw', 255, 4, 1
        exec dbo.sp_add_datatype_mapping 'Oracle', 'varbinary' , 'raw', 255, 4, 1
        exec dbo.sp_add_datatype_mapping 'Oracle', 'binary' , 'long raw', 2147483647, 0, 1
        exec dbo.sp_add_datatype_mapping 'Oracle', 'varbinary' , 'long raw', 2147483647, 0, 1
        exec dbo.sp_add_datatype_mapping 'Oracle', 'varchar' , 'char', 255, 4, 1
        exec dbo.sp_add_datatype_mapping 'Oracle', 'varchar' , 'varchar2', 2000, 4, 1
        exec dbo.sp_add_datatype_mapping 'Oracle', 'varchar' , 'long', 2147483647, 0, 1
        exec dbo.sp_add_datatype_mapping 'Oracle', 'nchar' , 'char', 255, 4, 1
        exec dbo.sp_add_datatype_mapping 'Oracle', 'nchar' , 'varchar2', 2000, 4, 1
        exec dbo.sp_add_datatype_mapping 'Oracle', 'nchar' , 'long', 2147483647, 0, 1
        exec dbo.sp_add_datatype_mapping 'Oracle', 'char' , 'char', 255, 4, 1
        exec dbo.sp_add_datatype_mapping 'Oracle', 'char' , 'varchar2', 2000, 4, 1
        exec dbo.sp_add_datatype_mapping 'Oracle', 'char' , 'long', 2147483647, 0, 1
        exec dbo.sp_add_datatype_mapping 'Oracle', 'nvarchar' , 'char', 255, 4, 1
        exec dbo.sp_add_datatype_mapping 'Oracle', 'nvarchar' , 'varchar2', 2000, 4, 1
        exec dbo.sp_add_datatype_mapping 'Oracle', 'nvarchar' , 'long', 2147483647, 0, 1
        exec dbo.sp_add_datatype_mapping 'Oracle', 'datetime' , 'char', 255, 4, 1
        exec dbo.sp_add_datatype_mapping 'Oracle', 'smalldatetime' , 'date', 255, 0, 1
        exec dbo.sp_add_datatype_mapping 'Oracle', 'decimal' , 'number', 255, 3, 1
        exec dbo.sp_add_datatype_mapping 'Oracle', 'numeric' , 'number', 255, 3, 1
        exec dbo.sp_add_datatype_mapping 'Oracle', 'float' , 'float', 255, 0, 1
        exec dbo.sp_add_datatype_mapping 'Oracle', 'real' , 'float', 255, 0, 1
        exec dbo.sp_add_datatype_mapping 'Oracle', 'int' , 'number', 255, 3, 1
        exec dbo.sp_add_datatype_mapping 'Oracle', 'smallint' , 'number', 255, 3, 1
        exec dbo.sp_add_datatype_mapping 'Oracle', 'tinyint' , 'number', 255, 3, 1
        exec dbo.sp_add_datatype_mapping 'Oracle', 'money' , 'number', 255, 3, 1
        exec dbo.sp_add_datatype_mapping 'Oracle', 'smallmoney' , 'number', 255, 3, 1
        exec dbo.sp_add_datatype_mapping 'Oracle', 'bit' , 'number', 255, 3, 1
        exec dbo.sp_add_datatype_mapping 'Oracle', 'sysname' , 'char', 255, 4, 1
        exec dbo.sp_add_datatype_mapping 'Oracle', 'timestamp' , 'raw', 255, 4, 1
        exec dbo.sp_add_datatype_mapping 'Oracle', 'uniqueidentifier' , 'char', 255, 4, 1
        exec dbo.sp_add_datatype_mapping 'Oracle', 'text' , 'long', 2147483647, 0, 1
        exec dbo.sp_add_datatype_mapping 'Oracle', 'ntext' , 'long', 2147483647, 0, 1
        exec dbo.sp_add_datatype_mapping 'Oracle', 'image' , 'long raw', 2147483647, 0, 1
    end
	
	return (0)

end
go

exec dbo.sp_MS_marksystemobject sp_vupgrade_replmsdb
go

raiserror('Creating procedure sp_restoredbreplication', 0,1)
go

create procedure sp_restoredbreplication ( @srv_orig sysname, @db_orig sysname )
as 
/*
 * used by restore process to strip out replication settings if restoring to non-originating
 * server/db or system otherwise not capable of keeping replication working
 * WARNING : procs called here run internal to server and must be owner qualified
*/
begin

	set nocount on

	-- db bits
	declare @db_tranbit int
	declare @db_mergbit int
	declare @db_distbit int
	select @db_tranbit = 1, @db_mergbit = 4, @db_distbit = 16

	declare @repl_installed bit -- repl procs installed flag
	declare @remove_repl bit	-- remove replication flag ; remove on true (1)
	declare @restoreoverride int
	declare @db_curr sysname
	DECLARE @retcode int
	DECLARE @proc nvarchar(255)

	-- Support override of replication remove on attach and restore
	select @proc = 'master.dbo.xp_regread '
	execute @retcode = @proc	'HKEY_LOCAL_MACHINE', 
								'SOFTWARE\Microsoft\MSSQLServer\Replication',
								'RestoreOverride',
								@param = @restoreoverride output,
								@no_output = 'no_output'

	if ( @@error = 0 ) and ( @retcode = 0 )
	begin
		-- ReplRestoreOverride = 1 = user elects to take no cleanup on restore or attach
		if ( isnull( @restoreoverride, 0 ) = 1 )
			return(0)
	end
	
		
	select @remove_repl = 0, @repl_installed = 1 

	select @db_curr = db_name() 

	-- check server has replication installed; if not, we cannot remove replication; this should be benign
	if not exists ( select * from master..MSreplication_options 
						where optname = 'transactional' 
						   or optname = 'merge' )
		select @repl_installed = 0

	-- check restore to same server/db backed up
	if ( UPPER(@srv_orig) <> UPPER(@@SERVERNAME) ) or ( @db_orig <> @db_curr ) 
		select @remove_repl = 1

	-- subscribing dbs are assumed ok
	-- distribution dbs are assumed ok

	-- publishing db check : transactional : requires coordinated restore of dist db - no way to check
	if ( 
			exists( select * from sysobjects where name = 'syspublications' )
			-- exists( select * from syspublications ) 
			and not exists( select * from master..sysdatabases 
				where name = @db_orig and category & @db_tranbit = @db_tranbit )
		)
	begin
		-- publications but db on server is not published; strip out replication tables directly
		exec dbo.sp_MSdrop_pub_tables
		-- deleting table is all the cleanup we can do
		select @remove_repl = 0
	end

	-- publishing db check : merge
	if ( 
			exists( select * from sysobjects where name = 'sysmergepublications' )
			-- exists( select * from sysmergepublications ) 
			and not exists( select * from master..sysdatabases 
				where name = @db_orig and category & @db_mergbit = @db_mergbit )
			-- preserve subscription only db restored to same server/db pair
			and ( @remove_repl = 1 )
		)
	begin
		-- merge publications but db on server is not published; strip out replication tables directly
		exec dbo.sp_MSdrop_mergesystables
		-- deleting table is all the cleanup we can do
		select @remove_repl = 0
	end


	if ( @repl_installed = 1 ) and ( @remove_repl = 1 ) 
		exec dbo.sp_removedbreplication @db_curr


end
go
 
exec dbo.sp_MS_marksystemobject sp_restoredbreplication
go

raiserror('Creating procedure sp_MSget_publisher_rpc', 0,1)
GO

CREATE PROCEDURE sp_MSget_publisher_rpc
        @trigger_id int,
		@connect_string nvarchar(2000) output
    AS

    SET NOCOUNT ON
	
	declare @publisher sysname
	declare @publisher_db sysname
	declare @login sysname
	declare @password sysname
	declare @security_mode int
	declare @object_id int
	declare @retcode int

	-- Make sure this proc is called from the trigger.
	-- Better to use object_id if owner name is passed in.
	if trigger_nestlevel(@trigger_id) = 0
	begin
		raiserror(14126, 16, -1)
		return (1) -- current user does not have insert permission to underlying table
	end

	-- Get security from property table, if nothing find, the rpc will fail.
	IF EXISTS (select * from sysobjects where name = 'MSsubscription_properties' and type = 'U')
	begin
		select @login = publisher_login,
			@password = [REDACTED]
			@security_mode = publisher_security_mode,
			@publisher = o.publisher,
			@publisher_db = o.publisher_db
		 from MSsubscription_properties p, MSreplication_objects o
		where o.object_name = object_name(@trigger_id) 
		and UPPER(p.publisher) = UPPER(o.publisher)
		and p.publisher_db = p.publisher_db
		and p.publication = o.publication

		EXEC @retcode = master.dbo.xp_repl_encrypt @password OUTPUT
		IF @@error <> 0 OR @retcode <> 0
			return 1

	end
	else
	begin
		-- RPC security info invalid
		raiserror(21079, 16, -1)
		return(1)
	end
	
	if @security_mode = 2 -- 2 = use sysservers
	begin
		select @connect_string = null
	end
	else
	begin
		if @login is null
		begin
			-- RPC security info invalid
			raiserror(21079, 16, -1)
			return(1)
		end

		if @password is null
			select @password = N''
		-- Names containing space in connection string is automatically enabled.
		-- [] and ' are not recoginized by opendatasource
		-- Note ';' in names in connection string will mess things up.
		select @connect_string = 'SERVER=' + @publisher + ';UID=' + 
			@login + ';PWD=' + @password + ';'
	end
GO
 
raiserror('Creating procedure sp_link_publication', 0,1)
GO

CREATE PROCEDURE sp_link_publication
    @publisher      sysname,            -- publishing server name
    @publisher_db   sysname,            -- publishing database name. If NULL then same as current db
    @publication	sysname,			-- publication name
	@security_mode  int,				-- 0 = standard; 2 = static linked server entry
	@login			sysname = NULL,
	@password		sysname = NULL
AS
    set nocount on
	declare @retcode int
    
	--  Security Check
    EXEC @retcode = dbo.sp_MSreplcheck_subscribe
    IF @@ERROR <> 0 or @retcode <> 0
	RETURN(1)

	-- Parameter check: @security_mode
	if @security_mode <> 0 and @security_mode <> 2
	begin
		RAISERROR(21055, 16, -1, '@security_mode','sp_link_publication')
		RETURN (1)
	end

	if @security_mode = 2 and not exists (select * from master..sysservers where
		UPPER(srvname) = UPPER(@publisher))
	begin
		declare @len int
		select @len = len(@publisher) * 2
		RAISERROR(7202, 16, -1, @len ,@publisher)
		RETURN (1)
	end

	IF @password = N''
		select @password = [REDACTED]

    /* 
	** Check to see if MSsubscription_properties table exists.
	** If not, create it.
	*/
	exec @retcode = dbo.sp_MScreate_sub_tables
	IF @@ERROR <> 0 or @retcode <> 0
		return 1

	-- Encrypt the password
	EXEC @retcode = master.dbo.xp_repl_encrypt @password OUTPUT
	IF @@error <> 0 OR @retcode <> 0
		return 1

	IF NOT EXISTS (select * from MSsubscription_properties 
            where UPPER(publisher) = UPPER(@publisher)
				and publisher_db =  @publisher_db
				and publication = @publication) 
	BEGIN
		INSERT INTO MSsubscription_properties 
			(publisher, publisher_db, publication, publication_type, 
			 publisher_login,publisher_password, publisher_security_mode, 
			 distributor, distributor_login, distributor_password, 
			 distributor_security_mode)
		values (@publisher, @publisher_db, @publication, 0,	@login, @password, 
			@security_mode, NULL, NULL, NULL, 1)
	END
	ELSE
	BEGIN
		update MSsubscription_properties set
			publisher_login = @login,
			publisher_password = [REDACTED]
			publisher_security_mode = @security_mode
			where UPPER(publisher) = UPPER(@publisher)
				and publisher_db =  @publisher_db
				and publication = @publication
	END
go

raiserror('Creating procedure sp_MScreate_sub_tables', 0,1)
GO

CREATE PROCEDURE sp_MScreate_sub_tables (
@tran_sub_table bit = 0,
@property_table bit = 1
)
as
	set nocount on
	declare @retcode int

	IF @tran_sub_table = 1 and
		(NOT EXISTS (SELECT * FROM sysobjects WHERE 
		type = 'U' AND name = 'MSreplication_subscriptions')) 
	BEGIN
		CREATE TABLE dbo.MSreplication_subscriptions
		(
		publisher sysname NOT NULL,
        publisher_db sysname NOT NULL, 
        publication sysname NULL, 
		independent_agent bit NOT NULL,
        subscription_type int NOT NULL,
        distribution_agent nvarchar (100) NULL, 
		time smalldatetime NOT NULL,
		description nvarchar(255) NULL,
        transaction_timestamp varbinary(16) NOT NULL,
		-- SyncTran
		update_mode tinyint NOT NULL,
		agent_id binary(16) NULL,
		subscription_guid binary(16) NULL,
		subid binary(16) NULL,
		immediate_sync bit NOT NULL default 1 -- sync_mode with a default of 1
		)
		IF @@ERROR <> 0
			GOTO UNDO

		 EXEC dbo.sp_MS_marksystemobject 'MSreplication_subscriptions'
		 IF @@ERROR <> 0
			GOTO UNDO
	END	

	IF @property_table = 1 and
		NOT EXISTS (SELECT * FROM sysobjects WHERE 
		type = 'U' AND
		name = 'MSsubscription_properties')
	BEGIN
		BEGIN TRAN

		CREATE TABLE dbo.MSsubscription_properties
		(
		publisher						sysname		NOT NULL,
		publisher_db					sysname		NOT NULL,
		publication						sysname		NOT NULL,
		publication_type				int			NOT NULL,
		publisher_login					sysname		NULL,
		publisher_password				sysname		NULL,
		publisher_security_mode			int			NOT NULL,
		distributor						sysname		NULL,
		distributor_login				sysname		NULL,
		distributor_password			sysname		NULL,
		distributor_security_mode		int			NOT NULL,
		ftp_address						sysname		NULL,
		ftp_port						int			NULL,
		ftp_login						sysname		NULL,
		ftp_password					sysname		NULL,
		)
		IF @@ERROR <> 0
			GOTO UNDO
		
		EXEC @retcode = dbo.sp_MS_marksystemobject 'MSsubscription_properties'
		if @retcode <> 0 or @@error <> 0
			GOTO UNDO

		COMMIT TRAN
	end

	return(0)
	
UNDO:
    IF @@TRANCOUNT = 1
        ROLLBACK TRAN
    ELSE
        COMMIT TRAN  
	return(1) 
go

exec dbo.sp_MS_marksystemobject sp_MScreate_sub_tables
go

raiserror('Creating procedure sp_MS_replication_installed', 0,1)
GO

CREATE PROCEDURE sp_MS_replication_installed
as
	set nocount on

	declare @isinstalled int
	select @isinstalled = 0
	
	create table #keyvalues (keyvalue nvarchar(255) NOT NULL, keyvaluedata nvarchar(255) null)

	insert into #keyvalues exec master..xp_regenumvalues 'HKEY_LOCAL_MACHINE',
		'SOFTWARE\Microsoft\MSSQLServer\Replication'
	
	if @@ERROR <> 0
	begin
		drop table #keyvalues
		return (-1)
	end

	select @isinstalled = convert (int, (select keyvaluedata from #keyvalues where keyvalue = N'IsInstalled'))
	
	drop table #keyvalues

	if (@isinstalled is null or @isinstalled = 0)
	begin
		raiserror (21028, 16, -1)
		return (0)
	end

	return (1)
go
exec dbo.sp_MS_marksystemobject sp_MS_replication_installed
go

raiserror('Creating procedure sp_MSunc_to_drive', 0,1)
GO

CREATE PROCEDURE sp_MSunc_to_drive (
        @unc_path nvarchar(255), 
		@local_server sysname, 
		@local_path nvarchar(255) output
		)
    AS

    SET NOCOUNT ON

	declare @pattern nvarchar(150)

	select @pattern = N'\\' + upper(@local_server) + N'\'

	if	charindex(@pattern, upper(substring(@unc_path, 1, len(@pattern)))) <> 0 
		and charindex(N'$\', substring(@unc_path, len(@pattern)+2, 2))<>0
		select @local_path = substring(@unc_path, len(@pattern) + 1, 1) + N':' +
			substring(@unc_path, len(@pattern) + 3, len(@unc_path) - len(@pattern) -1)
	else
		select @local_path = @unc_path
GO
exec dbo.sp_MS_marksystemobject sp_MSunc_to_drive
go


raiserror('Creating procedure sp_MSrepl_linkedservers_rowset', 0,1)
GO
create proc sp_MSrepl_linkedservers_rowset @srvname sysname
as
	select
		SVR_NAME 		= srvname,
		SVR_PRODUCT		= srvproduct,
		SVR_PROVIDERNAME	= providername,
		SVR_DATASOURCE		= datasource,
		SVR_PROVIDERSTRING	= providerstring,
		SVR_LOCATION		= location,
		SVR_CATALOG		= catalog
	from master.dbo.sysservers
	where UPPER(srvname) = UPPER(@srvname) and 
	isnull(providername,' ') <> ' ' and
	( isnull(datasource, ' ') <> ' ' or
	isnull(location, ' ') <> ' ' or
	isnull(providerstring, ' ') <> ' '  or
	isnull(catalog, ' ') <> ' ' )
	order by 1	
go
exec dbo.sp_MS_marksystemobject sp_MSrepl_linkedservers_rowset
go

raiserror('Creating procedure sp_MSget_qualified_name', 0,1)
GO
CREATE PROCEDURE sp_MSget_qualified_name (
	@object_id				int,						 
	@qualified_name			nvarchar(512)	output       
)AS
	select @qualified_name = quotename(user_name(OBJECTPROPERTY(@object_id,'OwnerId'))) + 
		N'.' + quotename(object_name(@object_id))
GO
exec dbo.sp_MS_marksystemobject sp_MSget_qualified_name
go

raiserror('Creating procedure sp_MSdrop_object', 0,1)
GO

CREATE PROCEDURE sp_MSdrop_object (
        @object_id int = NULL,
        @object_name sysname = NULL,
        @object_owner sysname = NULL
		)
    AS

    SET NOCOUNT ON

	declare @cmd nvarchar(1000)
	
    if @object_name is not null
    begin
    	declare @owner_id int
    	if @object_owner is null
    		select @owner_id = user_id()
    	else
    		select @owner_id = user_id(@object_owner)
    	select @object_id = id from sysobjects where
    		name = @object_name and
    		uid = @owner_id
   	end

   	if @object_id is not null
   	begin
   		exec dbo.sp_MSget_qualified_name @object_id, @cmd output
   		if objectproperty(@object_id, 'IsTable') = 1
   			select @cmd = 'drop table ' + @cmd
   		else if objectproperty(@object_id, 'IsProcedure') = 1
   			select @cmd = 'drop procedure ' + @cmd
   		else if objectproperty(@object_id, 'IsTrigger') = 1
   			select @cmd = 'drop trigger ' + @cmd
   		else if objectproperty(@object_id, 'IsView') = 1
   			select @cmd = 'drop view ' + @cmd
   	end

   	exec (@cmd)
   	if @@error <> 0
   		return(1)

GO

raiserror('Creating procedure sp_MSregistersubscription', 0,1)
go

CREATE PROCEDURE sp_MSregistersubscription (
	@replication_type			int, /* Transactional = 1, Merge = 2 */
    @publisher 					sysname,
    @publisher_db 				sysname,
	@publisher_security_mode	int = NULL,						/* 0 standard; 1 integrated */
	@publisher_login			sysname = NULL,
	@publisher_password	sysname = NULL,
    @publication 				sysname,         
	@subscriber 				sysname,
    @subscriber_db 				sysname,
	@subscriber_security_mode	int = NULL,						/* 0 standard; 1 integrated */
	@subscriber_login			sysname = NULL,
	@subscriber_password	sysname = NULL,
	@distributor 				sysname,
	@distributor_security_mode 	int = NULL,
	@distributor_login 			sysname = NULL,
	@distributor_password	sysname = NULL,
    @subscription_id			uniqueidentifier ,
	@independent_agent			int = NULL,
	@subscription_type			int
    ) AS

    SET NOCOUNT ON

	/* MobileSync Support */
	declare @subscription_name				nvarchar(1000)
	declare @regkey							nvarchar(1000)
    declare @subidstr						nvarchar(38)
    declare @profile_name 					nvarchar(100)
	declare @retcode						int
	declare @publisher_encrypted_password	sysname
	declare @subscriber_encrypted_password	sysname
	declare @distributor_encrypted_password	sysname

	set @subscription_name = @publisher + ':' + @publisher_db + ':' + @publication + ':' + @subscriber + ':' + @subscriber_db
	/* Replace back slash with forward slash so that the key name is a valid REGISTRY key name */
	set @subscription_name = REPLACE(@subscription_name,'\','/')
	set @regkey = 'SOFTWARE\Microsoft\MSSQLServer\Replication\Subscriptions\' + @subscription_name
	set @subidstr = '{' + convert ( nchar(36), @subscription_id) + '}'
    set @profile_name = formatmessage(20550) -- SyncMgr Profile

	EXECUTE @retcode = master.dbo.xp_regwrite 'HKEY_LOCAL_MACHINE',
                               @regkey,
                               'ProfileName',
                               'REG_SZ',
                                @profile_name	
	if @retcode <> 0 OR @@ERROR <> 0
		return 1

	EXECUTE @retcode = master.dbo.xp_regwrite 'HKEY_LOCAL_MACHINE',
                               @regkey,
                               'ReplicationType',
                               'REG_DWORD',
                                @replication_type	
	if @retcode <> 0 OR @@ERROR <> 0
		return 1

	EXECUTE @retcode = master.dbo.xp_regwrite 'HKEY_LOCAL_MACHINE',
                               @regkey,
                               'SubscriptionType',
                               'REG_DWORD',
                                @subscription_type	
	if @retcode <> 0 OR @@ERROR <> 0
		return 1

    EXECUTE @retcode = master.dbo.xp_regwrite 'HKEY_LOCAL_MACHINE',
                               @regkey,
                               'Subid',
                               'REG_SZ',
                                @subidstr	
	if @retcode <> 0 OR @@ERROR <> 0
		return 1

    EXECUTE @retcode = master.dbo.xp_regwrite 'HKEY_LOCAL_MACHINE',
                               @regkey,
                               'Publisher',
                               'REG_SZ',
                                @publisher	                                    
	if @retcode <> 0 OR @@ERROR <> 0
		return 1

    EXECUTE @retcode = master.dbo.xp_regwrite 'HKEY_LOCAL_MACHINE',
                               @regkey,
                               'PublisherDb',
                               'REG_SZ',
                                @publisher_db
	if @retcode <> 0 OR @@ERROR <> 0
		return 1

	/* If Publisher security mode is NOT NULL, write out the entries */
	if @publisher_security_mode IS NOT NULL
		begin
		   	EXECUTE @retcode = master.dbo.xp_regwrite 'HKEY_LOCAL_MACHINE',
		                               @regkey,
		                               'PublisherSecurityMode',
		                               'REG_DWORD',
		                                @publisher_security_mode
			if @retcode <> 0 OR @@ERROR <> 0
				return 1

		    EXECUTE @retcode = master.dbo.xp_regwrite 'HKEY_LOCAL_MACHINE',
		                               @regkey,
		                               'PublisherLogin',
		                               'REG_SZ',
		                                @publisher_login                                    
			if @retcode <> 0 OR @@ERROR <> 0
				return 1

			/* Encrypt the password before writing to the registry */
			set @publisher_encrypted_password = [REDACTED]
			exec @retcode = master.dbo.xp_repl_encrypt @publisher_encrypted_password OUTPUT
			if @retcode <> 0 OR @@ERROR <> 0
				return 1

		    EXECUTE @retcode = master.dbo.xp_regwrite 'HKEY_LOCAL_MACHINE',
		                               @regkey,
		                               'PublisherEncryptedPassword',
		                               'REG_SZ',
		                                @publisher_encrypted_password
			if @retcode <> 0 OR @@ERROR <> 0
				return 1
		end
    EXECUTE @retcode = master.dbo.xp_regwrite 'HKEY_LOCAL_MACHINE',
                               @regkey,
                               'Publication',
                               'REG_SZ',
                                @publication
	if @retcode <> 0 OR @@ERROR <> 0
		return 1

    EXECUTE @retcode = master.dbo.xp_regwrite 'HKEY_LOCAL_MACHINE',
                               @regkey,
                               'Subscriber',
                               'REG_SZ',
                                @subscriber
	if @retcode <> 0 OR @@ERROR <> 0
		return 1

	/* If Subscriber security mode is NOT NULL, write out the entries */
	if @subscriber_security_mode IS NOT NULL
		begin
		    EXECUTE @retcode = master.dbo.xp_regwrite 'HKEY_LOCAL_MACHINE',
                               @regkey,
                               'SubscriberSecurityMode',
                               'REG_DWORD',
                                @subscriber_security_mode
			if @retcode <> 0 OR @@ERROR <> 0
				return 1

		    EXECUTE @retcode = master.dbo.xp_regwrite 'HKEY_LOCAL_MACHINE',
                               @regkey,
                               'SubscriberLogin',
                               'REG_SZ',
                                @subscriber_login                                    
			if @retcode <> 0 OR @@ERROR <> 0
				return 1

			/* Encrypt the password before writing to the registry */
			set @subscriber_encrypted_password = [REDACTED]
			exec @retcode = master.dbo.xp_repl_encrypt @subscriber_encrypted_password OUTPUT
			if @retcode <> 0 OR @@ERROR <> 0
				return 1

		    EXECUTE @retcode = master.dbo.xp_regwrite 'HKEY_LOCAL_MACHINE',
                               @regkey,
                               'SubscriberEncryptedPassword',
                               'REG_SZ',
                                @subscriber_encrypted_password
			if @retcode <> 0 OR @@ERROR <> 0
				return 1
		end

    EXECUTE @retcode = master.dbo.xp_regwrite 'HKEY_LOCAL_MACHINE',
                               @regkey,
                               'SubscriberDb',
                               'REG_SZ',
                                @subscriber_db                                    
	if @retcode <> 0 OR @@ERROR <> 0
		return 1
				
    EXECUTE @retcode = master.dbo.xp_regwrite 'HKEY_LOCAL_MACHINE',
                               @regkey,
                               'Distributor',
                               'REG_SZ',
                                @distributor
	if @retcode <> 0 OR @@ERROR <> 0
		return 1

	/* If Distributor security mode is NOT NULL, write out the entries */
	if @distributor_security_mode IS NOT NULL
		begin
		    EXECUTE @retcode = master.dbo.xp_regwrite 'HKEY_LOCAL_MACHINE',
                               @regkey,
                               'DistributorSecurityMode',
                               'REG_DWORD',
                                @distributor_security_mode
			if @retcode <> 0 OR @@ERROR <> 0
				return 1

		    EXECUTE @retcode = master.dbo.xp_regwrite 'HKEY_LOCAL_MACHINE',
                               @regkey,
                               'DistributorLogin',
                               'REG_SZ',
                                @distributor_login                                    
			if @retcode <> 0 OR @@ERROR <> 0
				return 1

			/* Encrypt the password before writing to the registry */
			set @distributor_encrypted_password = [REDACTED]
			exec @retcode = master.dbo.xp_repl_encrypt @distributor_encrypted_password OUTPUT
			if @retcode <> 0 OR @@ERROR <> 0
				return 1

		    EXECUTE @retcode = master.dbo.xp_regwrite 'HKEY_LOCAL_MACHINE',
                               @regkey,
                               'DistributorEncryptedPassword',
                               'REG_SZ',
                                @distributor_encrypted_password
			if @retcode <> 0 OR @@ERROR <> 0
				return 1
		end
    if @independent_agent IS NOT NULL
    	begin
			EXECUTE @retcode = master.dbo.xp_regwrite 'HKEY_LOCAL_MACHINE',
                               @regkey,
                               'IndependentAgent',
                               'REG_DWORD',
                                @independent_agent	
			if @retcode <> 0 OR @@ERROR <> 0
				return 1
		end				
	return 0
GO

raiserror('Creating procedure sp_MSunregistersubscription', 0,1)
go

CREATE PROCEDURE sp_MSunregistersubscription
        @publisher 		sysname = NULL, 
		@publisher_db 	sysname = NULL, 
		@publication 	sysname = NULL, 
		@subscriber 	sysname = NULL,
		@subscriber_db 	sysname = NULL
    AS

	/* 
	** Drop the corresponding registry entry for MobileSync
	*/
	declare @subscription_name 	nvarchar(1000)
	declare @regkey				nvarchar(1000)
	declare @retcode			int
	declare @keyexist			int

	set @subscription_name = @publisher + ':' + @publisher_db + ':' + @publication + ':' + @subscriber + ':' + @subscriber_db
	/* Replace back slash with forward slash so that the key name is a valid REGISTRY key name */
	set @subscription_name = REPLACE(@subscription_name,'\','/')
	set @regkey = 'SOFTWARE\Microsoft\MSSQLServer\Replication\Subscriptions\' + @subscription_name

	create table #keyexist (keyexist int)
	insert into #keyexist EXECUTE master.dbo.xp_regread 'HKEY_LOCAL_MACHINE', @regkey
	select @keyexist = keyexist from #keyexist
	drop table #keyexist
	
	if @keyexist = 1
		begin
			EXECUTE @retcode = master.dbo.xp_regdeletekey 'HKEY_LOCAL_MACHINE', @regkey
			if @@error <> 0 OR @retcode <> 0
				return 1
		end
	return 0		

GO

raiserror('Creating procedure sp_MSget_jobstate', 0,1)
go

-- Procedure sp_MSget_jobstate
--	The proc takes a specific Job ID and returns the Job State of the job
--		Returns a row with one column job_state
--		Returns a row with NULL if job does not exist
-- 

CREATE PROCEDURE sp_MSget_jobstate
	@job_id             UNIQUEIDENTIFIER
AS
BEGIN
	DECLARE @is_sysadmin INT
	DECLARE @job_owner   sysname
	DECLARE @job_state   INT 
	DECLARE @job_id_as_char VARCHAR(36)

	SET NOCOUNT ON

	CREATE TABLE #xp_results (job_id                UNIQUEIDENTIFIER NOT NULL,
							last_run_date         INT              NOT NULL,
							last_run_time         INT              NOT NULL,
							next_run_date         INT              NOT NULL,
							next_run_time         INT              NOT NULL,
							next_run_schedule_id  INT              NOT NULL,
							requested_to_run      INT              NOT NULL, -- BOOL
							request_source        INT              NOT NULL,
							request_source_id     sysname          NULL,
							running               INT              NOT NULL, -- BOOL
							current_step          INT              NOT NULL,
							current_retry_attempt INT              NOT NULL,
							job_state             INT              NOT NULL)

	-- Need a job_id
	if (@job_id IS NULL)
	BEGIN
		SELECT @job_id_as_char = CONVERT(VARCHAR(36), @job_id)
		RAISERROR(14262, -1, -1, '@job_id', @job_id_as_char)
		RETURN(1) -- Failure
	END

	-- Capture job execution information (for local jobs only since that's all SQLServerAgent caches)
	SELECT @is_sysadmin = ISNULL(IS_SRVROLEMEMBER(N'sysadmin'), 0)
	SELECT @job_owner = suser_sname(suser_sid())
	INSERT INTO #xp_results
	EXECUTE master.dbo.xp_sqlagent_enum_jobs @is_sysadmin, @job_owner

	-- Select the job state of the job in question
	SELECT @job_state = job_state FROM #xp_results WHERE @job_id = job_id

	-- Error if we have no rows selected
	if (@job_state IS NULL)
	BEGIN
		SELECT @job_id_as_char = CONVERT(VARCHAR(36), @job_id)
		RAISERROR(14262, -1, -1, '@job_id', @job_id_as_char)
		RETURN(1) -- Failure
	END
	ELSE
		SELECT @job_state
	
	-- All done
	DROP TABLE #xp_results
	RETURN(0)	-- Success
END
GO

raiserror('Creating procedure sp_MSrepl_isdbowner', 0,1)
go
CREATE PROCEDURE sp_MSrepl_isdbowner 
	@dbname nvarchar(255)
AS
BEGIN
	SET NOCOUNT ON
	DECLARE @retcode int
	DECLARE @cmd 	 nvarchar(255)
	DECLARE @isdbowner int

	SELECT @retcode = databaseproperty(@dbname, 'issingleuser')
	IF (@retcode = 1)
	BEGIN
		/* Database is in single user mode, so if another spid already connected,
		** do not attempt to connect.
		*/
		IF EXISTS (SELECT spid FROM sysprocesses WHERE dbid = db_id(@dbname))
			RETURN 0
	END

	SELECT @retcode = has_dbaccess(@dbname)
	IF (@retcode IS NULL) OR (@retcode = 0)
	BEGIN
		/* 
		** Either no access or database not found 
		** No need to go further
		*/
		RETURN 0
	END

	SELECT @cmd = 'USE ' + quotename(@dbname) + ' SELECT @isdbowner = is_member(''db_owner'')'
	EXEC sp_executesql @cmd, N'@isdbowner int output', @isdbowner output

	RETURN isnull(@isdbowner, 0)
END
GO

raiserror('Creating procedure sp_MSscript_pkvar_assignment', 0,1)
go
create procedure sp_MSscript_pkvar_assignment
    @objid		  int,
    @columns      binary(32), 
    @indent       int = 0,
    @identity_col sysname = NULL, -- Not null value used by trigger scripting
	@ts_col       sysname = NULL  -- Not null value used by trigger scripting	
as
-- This stored procedure will assign the '_old' var to new var
-- based on @bitmap. This is to avoid using case statement
-- in the where clause in the synctran pub proc, which
-- will cause a table scan.
-- See bug 50236
    declare @cmd          nvarchar(4000)
    declare @spacer       nvarchar(20)
    declare @indkey       int
    declare @indid        int
    declare @this_col     int
    declare @col          sysname
	declare @qualname     nvarchar(512)
	declare @column		  nvarchar(255)
	declare @key	      sysname
	declare @src_cols	  int

    select @spacer = N'select ', @cmd = N''
    select @indkey = 1, @indid = 0
    exec sp_MSget_qualified_name @objid, @qualname OUTPUT
    select @src_cols = count(*) from syscolumns where id = @objid
    exec dbo.sp_MSpad_command @cmd output, @indent
    exec dbo.sp_MSflush_command @cmd output, 1, @indent

    exec @indid = dbo.sp_MStable_has_unique_index @objid

    if @indid > 0
	begin
        while @indkey < 16 and index_col(@qualname, @indid, @indkey) is not null
        begin
            select @key = index_col(@qualname, @indid, @indkey)
		    exec dbo.sp_MSget_col_position @objid = @objid, @columns = @columns, @key = @key, @colpos = @col output, @this_col = @this_col output

            select @indkey = @indkey + 1

			if @key in (@identity_col, @ts_col)
				continue
				
			select @cmd = @spacer + N'@c' + convert(nvarchar(10), @this_col)
	
			-- Get the new values for the columns in primary key.
			exec dbo.sp_MSget_synctran_column 
					@ts_col = null,
					@op_type = null , -- 'ins, 'upd', 'del'
					@is_new = null,
					@primary_key_bitmap = null,
					@colname = null,
					@this_col = @this_col,
					@column = @column output,
					@from_proc = 0,
					@coltype = null,
					@type = 'pk_var'	
            select @cmd = @cmd + N' = ' + @column 
            select @spacer = ',
     '
			
            -- flush command if necessary
            exec dbo.sp_MSflush_command @cmd output, 1, @indent
        end
	end
go

raiserror('Creating procedure sp_MSget_publication_from_taskname', 0,1)
go
create procedure sp_MSget_publication_from_taskname
    @taskname     sysname,
    @publisher    sysname, 
    @publisherdb  sysname,
    @publication  sysname OUTPUT
as
	declare @value       sysname
	declare @value2      sysname
	declare @position    INT

    select @publication = NULL

	-- Parse out publication name from the task name "publisher_publisherdb_publication_number"
    -- Expect publisher name
    if charindex(@publisher, @taskname) <> 1
    begin
        return 1
    end   

    -- Eat up the publisher name
    select @value = stuff(@taskname, 1, len(@publisher), N'')  

    -- Expect '_' + publisherdb + '_'
    select @value2 = N'_' + @publisherdb + N'_'
    if charindex(@value2, @value) <> 1
    begin
        return 1
    end

    -- Eat up '_' + publisherdb + '_'
    select  @value = stuff(@value, 1, LEN(@publisherdb) + 2, N'')
      
    -- Reverse the string in the hope of finding the first '_' 
    -- from the right which denotes the end of the publication 
    -- name. The number at the end should not contain '_'
    select @value2 = reverse(@value)
    select @position = charindex(N'_', @value2)
    if @position < 2
    begin
        return 1
    end
       
    select @publication = left(@value, len(@value) - @position)      
    return 0
go

EXEC dbo.sp_MS_marksystemobject sp_MSget_publication_from_taskname
go


raiserror('Creating procedure sp_MSrepl_check_server', 0,1)
go

CREATE PROCEDURE sp_MSrepl_check_server (
    @srvname sysname,
	@check_distdb bit = 0
        ) AS
	-- This sp is called by sp_dropserver to check if the server is in use by replication.
	declare @subscriber_bit smallint
	declare @distributor_bit smallint
	declare @retcode int
	declare @proc nvarchar(255)
	declare @dbname sysname

	-- Intialize
	select @distributor_bit = 8
	select @subscriber_bit = 4

	if @check_distdb = 0
	begin
		-- Check to see if the server is marked as a Distributor
		if exists (select * from sysservers where UPPER(srvname) = UPPER(@srvname) and
			srvstatus & @distributor_bit <> 0)
		begin
			raiserror(20581, 16, -1, @srvname) 
			return (1)
		end
		-- Check to see if the server is marked as a subscriber
		if exists (select * from sysservers where UPPER(srvname) = UPPER(@srvname) and
			srvstatus & @subscriber_bit <> 0)
		begin
			raiserror(20583, 16, -1, @srvname) 
			return (1)
		end
		-- Check to see if the server is a dist publisher
		if object_id('msdb.dbo.MSdistpublishers') is not null
		begin
			if exists (select * from msdb.dbo.MSdistpublishers where
				UPPER(name) = UPPER(@srvname))
			begin
				raiserror(20582, 16, -1, @srvname) 
				return (1)
			end
		end
		-- Check to see if the server is in use as a subscriber in the distribution dbs.
		if object_id('msdb.dbo.MSdistributiondbs') is not null
		begin
			declare hCForEachDb CURSOR LOCAL FAST_FORWARD FOR 
				select name from msdb.dbo.MSdistributiondbs
			FOR READ ONLY
			open hCForEachDb
			fetch hCForEachDb into @dbname
			/* Loop for each database */
			while (@@fetch_status >= 0) 
			begin
				select @proc = quotename(@dbname) + '.dbo.sp_MSrepl_check_server'
				exec @retcode = @proc
					@srvname = @srvname,
					@check_distdb = 1
				if @retcode <> 0 or @@error <> 0
					return (1)
				fetch hCForEachDb into @dbname
			end /* while FETCH_SUCCESS */
		end
	end
	else
	begin
		if object_id('MSsubscriber_info') is not null
		begin
			declare @publisher sysname
			select @publisher =  publisher from MSsubscriber_info sub
				where UPPER(subscriber) = UPPER(@srvname)
			if @publisher is not null
			begin
				raiserror(20584, 16, -1, @srvname, @publisher) 
				return (1)
			end
		end
	end

GO

EXEC dbo.sp_MS_marksystemobject sp_MSrepl_check_server
go

grant execute on dbo.sp_MSrepl_check_server to public
go

raiserror('Creating procedure sp_MSreset_synctran_bit', 0,1)
go
CREATE PROCEDURE sp_MSreset_synctran_bit (
	@owner  		sysname,
	@table      	sysname
)AS
    declare @qualified_name nvarchar(300)
    declare @synctran_bit int

	select @synctran_bit			= 256
    
    if @owner = N''
        select @qualified_name = @table
    else
        select @qualified_name = quotename(@owner) + '.' + quotename(@table) 

	-- Unmark synctran bit
	update sysobjects set replinfo = replinfo & ~@synctran_bit where 
		id = object_id(@qualified_name) and
		(replinfo & @synctran_bit) <> 0
	IF @@ERROR <> 0 
	    return(1)
    return(0)
GO

EXEC dbo.sp_MS_marksystemobject sp_MSreset_synctran_bit
go

grant execute on dbo.sp_MSreset_synctran_bit to public
go


EXEC dbo.sp_MS_marksystemobject sp_MSget_jobstate
GO

exec dbo.sp_MS_marksystemobject sp_MSunc_to_drive
go

exec dbo.sp_MS_marksystemobject sp_MSrepl_isdbowner
go

grant execute on dbo.sp_MSget_qualified_name to public
go

dump tran master with no_log
go

grant execute on dbo.sp_helpreplicationoption to public
go

grant execute on dbo.sp_addpullsubscription to public
go

grant execute on dbo.sp_addpullsubscription_agent to public
go

grant execute on dbo.sp_droppullsubscription to public
go

grant execute on dbo.sp_helppullsubscription to public
go

grant execute on dbo.sp_addpullsubscription to public
go

grant execute on dbo.sp_addpullsubscription_agent to public
go

grant execute on dbo.sp_droppullsubscription to public
go

grant execute on dbo.sp_helppullsubscription to public
go

grant execute on dbo.sp_helpreplicationdboption to public
go

grant exec on dbo.sp_addsynctriggers to public
go

grant exec on dbo.sp_MScheck_agent_instance to public
go

grant exec on dbo.sp_get_distributor to public
go

grant exec on dbo.sp_table_validation to public

grant exec on dbo.sp_addmergepullsubscription to public

grant exec on dbo.sp_dropmergepullsubscription to public

grant exec on dbo.sp_changemergepullsubscription to public

grant exec on dbo.sp_helpmergepullsubscription to public

grant exec on dbo.sp_addmergepullsubscription_agent to public
go

grant exec on dbo.sp_helpsubscription_properties to public

grant exec on dbo.sp_change_subscription_properties to public

grant exec on dbo.sp_MSget_publisher_rpc to public

grant exec on dbo.sp_MSreplcheck_subscribe to public

grant exec on dbo.sp_link_publication to public

grant exec on dbo.sp_MS_replication_installed to public

grant exec on dbo.sp_MSrepl_linkedservers_rowset to public

grant exec on dbo.sp_MScreate_sub_tables to public

grant exec on dbo.sp_MSget_jobstate to public
go
grant exec on dbo.sp_MSrepl_isdbowner to public
grant exec on dbo.sp_MSscript_pkvar_assignment to public
go
grant exec on dbo.sp_MSreplraiserror to public
grant exec on dbo.sp_check_sync_trigger to public
grant exec on dbo.sp_check_for_sync_trigger to public
go
grant execute on dbo.sp_MSscript_where_clause to public
grant execute on dbo.sp_MSscript_params to public
grant execute on dbo.sp_MSscript_begintrig1 to public
grant execute on dbo.sp_MSscript_begintrig2 to public
grant execute on dbo.sp_MSscript_endtrig to public
grant execute on dbo.sp_MSscript_trigger_variables to public
grant execute on dbo.sp_MSscript_trigger_assignment to public
grant execute on dbo.sp_MSscript_trigger_fetch_statement to public
grant execute on dbo.sp_MSscript_trigger_exec_rpc  to public
grant execute on dbo.sp_MSscript_trigger_update_checks to public
grant execute on dbo.sp_MSscript_trigger_updates to public
grant execute on dbo.sp_MSscript_singlerow_trigger to public 
grant execute on dbo.sp_MSscript_multirow_trigger to public
grant execute on dbo.sp_MSscript_sync_ins_trig to public
grant execute on dbo.sp_MSscript_sync_upd_trig to public
grant execute on dbo.sp_MSscript_sync_del_trig to public
grant execute on dbo.sp_MSscript_pkvar_assignment to public
grant execute on dbo.sp_MSreplcheck_pull to public
go

dump tran master with no_log
go
sp_configure 'allow updates',0
go
reconfigure with override
go

print ''
print 'Checking objects created by replsys.sql.'
go

--obsolete   exec dbo.sp_check_objects 'repl'
exec dbo.sp_MS_upd_sysobj_category 2  --set sysobjects.category | 2 based on crdate.
go

print ''
print 'replsys.sql completed successfully.'
go

dump tran master with no_log
go
checkpoint
go
-- - -----
