def deploy_windows(host,
                   port=445,
                   timeout=900,
                   username='Administrator',
                   password=None,
                   name=None,
                   sock_dir=None,
                   conf_file=None,
                   start_action=None,
                   parallel=False,
                   minion_pub=None,
                   minion_pem=None,
                   minion_conf=None,
                   keep_tmp=False,
                   script_args=None,
                   script_env=None,
                   port_timeout=15,
                   preseed_minion_keys=None,
                   win_installer=None,
                   master=None,
                   tmp_dir='C:\\salttmp',
                   opts=None,
                   master_sign_pub_file=None,
                   use_winrm=False,
                   winrm_port=5986,
                   winrm_use_ssl=True,
                   winrm_verify_ssl=True,
                   **kwargs):
    '''
    Copy the install files to a remote Windows box, and execute them
    '''
    if not isinstance(opts, dict):
        opts = {}

    if use_winrm and not HAS_WINRM:
        log.error('WinRM requested but module winrm could not be imported')
        return False

    if not use_winrm and has_winexe() and not HAS_PSEXEC:
        salt.utils.versions.warn_until(
            'Sodium',
            'Support for winexe has been deprecated and will be removed in '
            'Sodium, please install pypsexec instead.'
        )

    starttime = time.mktime(time.localtime())
    log.debug('Deploying %s at %s (Windows)', host, starttime)
    log.trace('HAS_WINRM: %s, use_winrm: %s', HAS_WINRM, use_winrm)

    port_available = wait_for_port(host=host, port=port, timeout=port_timeout * 60)

    if not port_available:
        return False

    service_available = False
    winrm_session = None

    if HAS_WINRM and use_winrm:
        winrm_session = wait_for_winrm(host=host, port=winrm_port,
                                       username=username, password=password,
                                       timeout=port_timeout * 60, use_ssl=winrm_use_ssl,
                                       verify=winrm_verify_ssl)
        if winrm_session is not None:
            service_available = True
    else:
        service_available = wait_for_psexecsvc(host=host, port=port,
                                               username=username, password=password,
                                               timeout=port_timeout * 60)

    if port_available and service_available:
        log.debug('SMB port %s on %s is available', port, host)
        log.debug('Logging into %s:%s as %s', host, port, username)
        newtimeout = timeout - (time.mktime(time.localtime()) - starttime)
        smb_conn = salt.utils.smb.get_conn(host, username, password)
        if smb_conn is False:
            log.error('Please install smbprotocol to enable SMB functionality')
            return False

        salt.utils.smb.mkdirs('salttemp', conn=smb_conn)
        salt.utils.smb.mkdirs('salt/conf/pki/minion', conn=smb_conn)

        if minion_pub:
            salt.utils.smb.put_str(minion_pub, 'salt\\conf\\pki\\minion\\minion.pub', conn=smb_conn)

        if minion_pem:
            salt.utils.smb.put_str(minion_pem, 'salt\\conf\\pki\\minion\\minion.pem', conn=smb_conn)

        if master_sign_pub_file:
            # Read master-sign.pub file
            log.debug("Copying master_sign.pub file from %s to minion", master_sign_pub_file)
            try:
                salt.utils.smb.put_file(
                    master_sign_pub_file,
                    'salt\\conf\\pki\\minion\\master_sign.pub',
                    'C$',
                    conn=smb_conn,
                )
            except Exception as e:
                log.debug("Exception copying master_sign.pub file %s to minion", master_sign_pub_file)

        # Copy over win_installer
        # win_installer refers to a file such as:
        # /root/Salt-Minion-0.17.0-win32-Setup.exe
        # ..which exists on the same machine as salt-cloud
        comps = win_installer.split('/')
        local_path = '/'.join(comps[:-1])
        installer = comps[-1]
        salt.utils.smb.put_file(
            win_installer,
            'salttemp\\{0}'.format(installer),
            'C$',
            conn=smb_conn,
        )

        if use_winrm:
            winrm_cmd(winrm_session, 'c:\\salttemp\\{0}'.format(installer), ['/S', '/master={0}'.format(master),
                                                                             '/minion-name={0}'.format(name)]
            )
        else:
            cmd = 'c:\\salttemp\\{0}'.format(installer)
            args = "/S /master={0} /minion-name={1}".format(master, name)
            stdout, stderr, ret_code = run_psexec_command(
                cmd, args, host, username, password
            )

            if ret_code != 0:
                raise Exception('Fail installer {0}'.format(ret_code))

        # Copy over minion_conf
        if minion_conf:
            if not isinstance(minion_conf, dict):
                # Let's not just fail regarding this change, specially
                # since we can handle it
                raise DeprecationWarning(
                    '`salt.utils.cloud.deploy_windows` now only accepts '
                    'dictionaries for its `minion_conf` parameter. '
                    'Loading YAML...'
                )
            minion_grains = minion_conf.pop('grains', {})
            if minion_grains:
                salt.utils.smb.put_str(
                    salt_config_to_yaml(minion_grains, line_break='\r\n'),
                    'salt\\conf\\grains',
                    conn=smb_conn
                )
            # Add special windows minion configuration
            # that must be in the minion config file
            windows_minion_conf = {
                'ipc_mode': 'tcp',
                'root_dir': 'c:\\salt',
                'pki_dir': '/conf/pki/minion',
                'multiprocessing': False,
            }
            minion_conf = dict(minion_conf, **windows_minion_conf)
            salt.utils.smb.put_str(
                salt_config_to_yaml(minion_conf, line_break='\r\n'),
                'salt\\conf\\minion',
                conn=smb_conn
            )
        # Delete C:\salttmp\ and installer file
        # Unless keep_tmp is True
        if not keep_tmp:
            if use_winrm:
                winrm_cmd(winrm_session, 'rmdir', ['/Q', '/S', 'C:\\salttemp\\'])
            else:
                salt.utils.smb.delete_file('salttemp\\{0}'.format(installer), 'C$', conn=smb_conn)
                salt.utils.smb.delete_directory('salttemp', 'C$', conn=smb_conn)
        # Shell out to psexec to ensure salt-minion service started
        if use_winrm:
            winrm_cmd(winrm_session, 'sc', ['stop', 'salt-minion'])
            time.sleep(5)
            winrm_cmd(winrm_session, 'sc', ['start', 'salt-minion'])
        else:
            stdout, stderr, ret_code = run_psexec_command(
                'cmd.exe', '/c sc stop salt-minion', host, username, password
            )
            if ret_code != 0:
                return False

            time.sleep(5)

            log.debug('Run psexec: sc start salt-minion')
            stdout, stderr, ret_code = run_psexec_command(
                'cmd.exe', '/c sc start salt-minion', host, username, password
            )
            if ret_code != 0:
                return False

        # Fire deploy action
        fire_event(
            'event',
            '{0} has been deployed at {1}'.format(name, host),
            'salt/cloud/{0}/deploy_windows'.format(name),
            args={'name': name},
            sock_dir=opts.get(
                'sock_dir',
                os.path.join(__opts__['sock_dir'], 'master')),
            transport=opts.get('transport', 'zeromq')
        )

        return True
    return False