summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHugo Landau <hlandau@openssl.org>2023-04-18 19:30:55 +0100
committerHugo Landau <hlandau@openssl.org>2023-05-12 14:47:12 +0100
commitcb68ce9fa7e2312afd8e5346a799d32024b67d02 (patch)
tree08174897813e28d600f9da0144ab761061bc8b8c
parent8a90df343edb194920b7a01c8b5e47d8b6e952c5 (diff)
QUIC DISPATCH/APL: SSL_accept_stream, SSL_get_accept_queue_len
Reviewed-by: Matt Caswell <matt@openssl.org> Reviewed-by: Tomas Mraz <tomas@openssl.org> (Merged from https://github.com/openssl/openssl/pull/20765)
-rw-r--r--include/internal/quic_ssl.h2
-rw-r--r--include/openssl/ssl.h.in4
-rw-r--r--ssl/quic/quic_impl.c129
-rw-r--r--ssl/ssl_lib.c24
-rw-r--r--util/libssl.num2
5 files changed, 161 insertions, 0 deletions
diff --git a/include/internal/quic_ssl.h b/include/internal/quic_ssl.h
index d307a9e196..ed17005843 100644
--- a/include/internal/quic_ssl.h
+++ b/include/internal/quic_ssl.h
@@ -74,6 +74,8 @@ __owur SSL *ossl_quic_detach_stream(SSL *s);
__owur int ossl_quic_attach_stream(SSL *conn, SSL *stream);
__owur int ossl_quic_set_incoming_stream_reject_policy(SSL *s, int policy,
uint64_t aec);
+__owur SSL *ossl_quic_accept_stream(SSL *s, uint64_t flags);
+__owur size_t ossl_quic_get_accept_stream_queue_len(SSL *s);
/*
* Used to override ossl_time_now() for debug purposes. Must be called before
diff --git a/include/openssl/ssl.h.in b/include/openssl/ssl.h.in
index d29ad85ece..dcc7cfdb3a 100644
--- a/include/openssl/ssl.h.in
+++ b/include/openssl/ssl.h.in
@@ -2293,6 +2293,10 @@ __owur SSL *SSL_new_stream(SSL *s, uint64_t flags);
#define SSL_INCOMING_STREAM_REJECT_POLICY_REJECT 2
__owur int SSL_set_incoming_stream_reject_policy(SSL *s, int policy, uint64_t aec);
+#define SSL_ACCEPT_STREAM_NO_BLOCK (1U << 0)
+__owur SSL *SSL_accept_stream(SSL *s, uint64_t flags);
+__owur size_t SSL_get_accept_stream_queue_len(SSL *s);
+
# ifndef OPENSSL_NO_QUIC
__owur int SSL_inject_net_dgram(SSL *s, const unsigned char *buf,
size_t buf_len,
diff --git a/ssl/quic/quic_impl.c b/ssl/quic/quic_impl.c
index e76526a1b9..840dcfed96 100644
--- a/ssl/quic/quic_impl.c
+++ b/ssl/quic/quic_impl.c
@@ -1991,6 +1991,7 @@ int ossl_quic_get_stream_type(SSL *s)
* SSL_get_stream_id
* -----------------
*/
+QUIC_TAKES_LOCK
uint64_t ossl_quic_get_stream_id(SSL *s)
{
QCTX ctx;
@@ -2009,6 +2010,7 @@ uint64_t ossl_quic_get_stream_id(SSL *s)
* SSL_set_default_stream_mode
* ---------------------------
*/
+QUIC_TAKES_LOCK
int ossl_quic_set_default_stream_mode(SSL *s, uint32_t mode)
{
QCTX ctx;
@@ -2042,6 +2044,7 @@ int ossl_quic_set_default_stream_mode(SSL *s, uint32_t mode)
* SSL_detach_stream
* -----------------
*/
+QUIC_TAKES_LOCK
SSL *ossl_quic_detach_stream(SSL *s)
{
QCTX ctx;
@@ -2067,6 +2070,7 @@ SSL *ossl_quic_detach_stream(SSL *s)
* SSL_attach_stream
* -----------------
*/
+QUIC_TAKES_LOCK
int ossl_quic_attach_stream(SSL *conn, SSL *stream)
{
QCTX ctx;
@@ -2099,6 +2103,7 @@ int ossl_quic_attach_stream(SSL *conn, SSL *stream)
* SSL_set_incoming_stream_reject_policy
* -------------------------------------
*/
+QUIC_TAKES_LOCK
int ossl_quic_set_incoming_stream_reject_policy(SSL *s, int policy,
uint64_t aec)
{
@@ -2128,6 +2133,130 @@ int ossl_quic_set_incoming_stream_reject_policy(SSL *s, int policy,
}
/*
+ * SSL_accept_stream
+ * -----------------
+ */
+QUIC_NEEDS_LOCK
+static int qc_get_effective_incoming_stream_reject_policy(QUIC_CONNECTION *qc)
+{
+ switch (qc->incoming_stream_reject_policy) {
+ case SSL_INCOMING_STREAM_REJECT_POLICY_AUTO:
+ if ((qc->default_xso == NULL && qc->default_xso_created)
+ || qc->default_stream_mode == SSL_DEFAULT_STREAM_MODE_NONE)
+ return SSL_INCOMING_STREAM_REJECT_POLICY_ACCEPT;
+ else
+ return SSL_INCOMING_STREAM_REJECT_POLICY_REJECT;
+
+ default:
+ return qc->incoming_stream_reject_policy;
+ }
+}
+
+struct wait_for_incoming_stream_args {
+ QUIC_CONNECTION *qc;
+ QUIC_STREAM *qs;
+};
+
+QUIC_NEEDS_LOCK
+static int wait_for_incoming_stream(void *arg)
+{
+ struct wait_for_incoming_stream_args *args = arg;
+ QUIC_STREAM_MAP *qsm = ossl_quic_channel_get_qsm(args->qc->ch);
+
+ if (!ossl_quic_channel_is_active(args->qc->ch)) {
+ /* If connection is torn down due to an error while blocking, stop. */
+ QUIC_RAISE_NON_NORMAL_ERROR(args->qc, SSL_R_PROTOCOL_IS_SHUTDOWN, NULL);
+ return -1;
+ }
+
+ args->qs = ossl_quic_stream_map_peek_accept_queue(qsm);
+ if (args->qs != NULL)
+ return 1; /* got a stream */
+
+ return 0; /* did not get a stream, keep trying */
+}
+
+QUIC_TAKES_LOCK
+SSL *ossl_quic_accept_stream(SSL *s, uint64_t flags)
+{
+ QCTX ctx;
+ int ret;
+ SSL *new_s = NULL;
+ QUIC_STREAM_MAP *qsm;
+ QUIC_STREAM *qs;
+ QUIC_XSO *xso;
+
+ if (!expect_quic_conn_only(s, &ctx))
+ return NULL;
+
+ quic_lock(ctx.qc);
+
+ if (qc_get_effective_incoming_stream_reject_policy(ctx.qc)
+ == SSL_INCOMING_STREAM_REJECT_POLICY_REJECT)
+ goto out;
+
+ qsm = ossl_quic_channel_get_qsm(ctx.qc->ch);
+
+ qs = ossl_quic_stream_map_peek_accept_queue(qsm);
+ if (qs == NULL) {
+ if (qc_blocking_mode(ctx.qc)
+ && (flags & SSL_ACCEPT_STREAM_NO_BLOCK) == 0) {
+ struct wait_for_incoming_stream_args args;
+
+ args.qc = ctx.qc;
+ args.qs = NULL;
+
+ ret = block_until_pred(ctx.qc, wait_for_incoming_stream, &args, 0);
+ if (ret == 0) {
+ QUIC_RAISE_NON_NORMAL_ERROR(ctx.qc, ERR_R_INTERNAL_ERROR, NULL);
+ goto out;
+ } else if (ret < 0 || args.qs == NULL) {
+ goto out;
+ }
+
+ qs = args.qs;
+ } else {
+ goto out;
+ }
+ }
+
+ xso = create_xso_from_stream(ctx.qc, qs);
+ if (xso == NULL)
+ goto out;
+
+ ossl_quic_stream_map_remove_from_accept_queue(qsm, qs);
+ new_s = &xso->ssl;
+
+ /* Calling this function inhibits default XSO autocreation. */
+ ctx.qc->default_xso_created = 1;
+
+out:
+ quic_unlock(ctx.qc);
+ return new_s;
+}
+
+/*
+ * SSL_get_accept_stream_queue_len
+ * -------------------------------
+ */
+QUIC_TAKES_LOCK
+size_t ossl_quic_get_accept_stream_queue_len(SSL *s)
+{
+ QCTX ctx;
+ size_t v;
+
+ if (!expect_quic_conn_only(s, &ctx))
+ return 0;
+
+ quic_lock(ctx.qc);
+
+ v = ossl_quic_stream_map_get_accept_queue_len(ossl_quic_channel_get_qsm(ctx.qc->ch));
+
+ quic_unlock(ctx.qc);
+ return v;
+}
+
+/*
* QUIC Front-End I/O API: SSL_CTX Management
* ==========================================
*/
diff --git a/ssl/ssl_lib.c b/ssl/ssl_lib.c
index 6e3ef08376..1d84ac39dc 100644
--- a/ssl/ssl_lib.c
+++ b/ssl/ssl_lib.c
@@ -7400,6 +7400,30 @@ int SSL_set_incoming_stream_reject_policy(SSL *s, int policy, uint64_t aec)
#endif
}
+SSL *SSL_accept_stream(SSL *s, uint64_t flags)
+{
+#ifndef OPENSSL_NO_QUIC
+ if (!IS_QUIC(s))
+ return NULL;
+
+ return ossl_quic_accept_stream(s, flags);
+#else
+ return NULL;
+#endif
+}
+
+size_t SSL_get_accept_stream_queue_len(SSL *s)
+{
+#ifndef OPENSSL_NO_QUIC
+ if (!IS_QUIC(s))
+ return 0;
+
+ return ossl_quic_get_accept_stream_queue_len(s);
+#else
+ return 0;
+#endif
+}
+
int SSL_add_expected_rpk(SSL *s, EVP_PKEY *rpk)
{
unsigned char *data = NULL;
diff --git a/util/libssl.num b/util/libssl.num
index ab28742a81..b99ed33a9e 100644
--- a/util/libssl.num
+++ b/util/libssl.num
@@ -569,3 +569,5 @@ SSL_set_default_stream_mode ? 3_2_0 EXIST::FUNCTION:
SSL_detach_stream ? 3_2_0 EXIST::FUNCTION:
SSL_attach_stream ? 3_2_0 EXIST::FUNCTION:
SSL_set_incoming_stream_reject_policy ? 3_2_0 EXIST::FUNCTION:
+SSL_accept_stream ? 3_2_0 EXIST::FUNCTION:
+SSL_get_accept_stream_queue_len ? 3_2_0 EXIST::FUNCTION:
#n591'>591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748
# Microsoft Developer Studio Generated NMAKE File, Format Version 4.00
# ** DO NOT EDIT **
#
# Make_ivc.mak Makefile to build vim in both IDE and nmake.
# This file can be imported as a workspace into Visual Studio.  It must be in
# DOS fileformat then!
#
# It is worth making the file read-only as the VC4 IDE will try to overwrite
# it with a HUGELY expanded clone of itself.
#
# The following points are worth noting:
# 1) Comments here are ignored by VC[456].0 IDEs
# 2) # ADD LINK32 /pdb:.\Dbg/vimd.pdb is written so rather than
#    # ADD LINK32 /pdb:".\Dbg/vimd.pdb" to avoid VC4 -> VC5 conversion failure
# 3) It is good to delete .pdb file before linking to cope with switch among
#    VC[456] as IDE clean action does not remove that file and link clashes
#    with it. The following works in VC5 but not in VC4 which does not support
#    pre-link actions. The nmake action does such deletions.
# Begin Special Build Tool
PreLink_Cmds=@if exist .\oleDbg\gvimd.pdb del .\oleDbg\gvimd.pdb
# End Special Build Tool
# 4) I was unable to make !IFDEF OLE, etc. work in the VC4 IDE.
#    I was aiming for 4 configurations with sub-configurations selected by
#    environment variables.
# 5) Optimisation is not supported by disabled versions of VC. This results in
#    messages for Release builds like:
#      Command line warning D4025 : overriding '/O2' with '/Od'
# 6) nmake 1.62 and later support batch compilation. I was unable to use this
#    in a manner acceptable to earlier IDEs.
#
# History
#
# When       Who       What
# 2001-07-06 W.Briscoe Original derived from Make_[go]vc.mak with less noise
# 2001-07-08 W.Briscoe Further noise reduction; consistent .map and .pdb logic
#		       Added install.exe rule, etc.; Removed unused libraries.
# 2001-08-09 W.Briscoe Restored VC4.0-required trailing space in !MESSAGE afore
#		       Enhanced if_ole.idl rule to use /out argument.
#		       Default rules now relative to . to reduce IDE/nmake difs

# TARGTYPE "Win32 (x86) Console Application" 0x0103

!IF "$(CFG)" == ""
CFG=Vim - Win32 Release gvim OLE
!MESSAGE No configuration specified.  Defaulting to Vim - Win32 Release gvim OLE.
!ENDIF

!IF "$(CFG)" != "Vim - Win32 Release gvim OLE"\
 && "$(CFG)" != "Vim - Win32 Debug gvim OLE"\
 && "$(CFG)" != "Vim - Win32 Release gvim"\
 && "$(CFG)" != "Vim - Win32 Debug gvim"\
 && "$(CFG)" != "Vim - Win32 Release vim"\
 && "$(CFG)" != "Vim - Win32 Debug vim"
!MESSAGE Invalid configuration "$(CFG)" specified.
!MESSAGE You can specify a configuration when running NMAKE on this makefile
!MESSAGE by defining the macro CFG on the command line.  For example:
!MESSAGE
!MESSAGE NMAKE /f "Make_ivc.mak" CFG="Vim - Win32 Debug vim"
!MESSAGE
!MESSAGE Possible choices for configuration are:
!MESSAGE
!MESSAGE "Vim - Win32 Release gvim OLE" (based on "Win32 (x86) Console Application")
!MESSAGE "Vim - Win32 Debug gvim OLE"   (based on "Win32 (x86) Console Application")
!MESSAGE "Vim - Win32 Release gvim"     (based on "Win32 (x86) Console Application")
!MESSAGE "Vim - Win32 Debug gvim"       (based on "Win32 (x86) Console Application")
!MESSAGE "Vim - Win32 Release vim"      (based on "Win32 (x86) Console Application")
!MESSAGE "Vim - Win32 Debug vim"        (based on "Win32 (x86) Console Application")
!MESSAGE 
!ERROR An invalid configuration is specified.
!ENDIF

!IF "$(OS)" == "Windows_NT"
NULL=
DEL_TREE = rmdir /s /q
!ELSE
NULL=nul
DEL_TREE = deltree /y
!ENDIF

# Begin Project
# PROP Target_Last_Scanned "Vim - Win32 Debug vim"
# PROP Use_MFC 0

RSC=rc.exe
CPP=cl.exe
LINK32=link.exe

CPP_PROJ= /nologo /MT /W3 /GX /I ".\proto" /D "WIN32" /c
# ADD CPP /nologo /MT /W3 /GX /I ".\proto" /D "WIN32" /c

LINK32_FLAGS= oldnames.lib kernel32.lib user32.lib gdi32.lib version.lib comdlg32.lib comctl32.lib advapi32.lib shell32.lib ole32.lib uuid.lib /nologo /machine:I386 /nodefaultlib
# ADD LINK32  oldnames.lib kernel32.lib user32.lib gdi32.lib version.lib comdlg32.lib comctl32.lib advapi32.lib shell32.lib ole32.lib uuid.lib /nologo /machine:I386 /nodefaultlib
# SUBTRACT LINK32 /incremental:yes

RSC_PROJ= /l 0x409 /d "FEAT_GUI_W32"
# ADD RSC /l 0x409 /d "FEAT_GUI_W32"

!IF  "$(CFG)" == "Vim - Win32 Release gvim OLE"

# PROP Use_Debug_Libraries 0
# PROP Output_Dir .\oleRel
# PROP Intermediate_Dir .\oleRel

INTDIR=.\oleRel
VIM=gvim
EXTRAS="$(INTDIR)/if_ole.obj" "$(INTDIR)/vim.res" "$(INTDIR)/gui.obj" "$(INTDIR)/gui_w32.obj" "$(INTDIR)/gui_beval.obj" "$(INTDIR)/os_w32exe.obj"

CPP_PROJ=$(CPP_PROJ) /Zi /O2 /D "NDEBUG" /D "FEAT_GUI_W32" /D "DYNAMIC_GETTEXT" /D "FEAT_OLE" /Fd.\oleRel/ /Fo.\oleRel/
# ADD CPP            /Zi /O2 /D "NDEBUG" /D "FEAT_GUI_W32" /D "DYNAMIC_GETTEXT" /D "FEAT_OLE" /Fd.\oleRel/ /Fo.\oleRel/

RSC_PROJ=$(RSC_PROJ) /I ".\oleRel" /d "NDEBUG" /d "FEAT_OLE" /fo.\oleRel\vim.res
# ADD RSC            /I ".\oleRel" /d "NDEBUG" /d "FEAT_OLE" /fo.\oleRel\vim.res

LINK32_FLAGS=$(LINK32_FLAGS) /pdb:.\oleRel/gvim.pdb -debug:full -debugtype:cv,fixup /map:.\oleDbg\gvim.map libc.lib oleaut32.lib /subsystem:windows /out:.\gvim.exe
# ADD LINK32                 /pdb:.\oleRel/gvim.pdb -debug:full -debugtype:cv,fixup /map:.\oleDbg\gvim.map libc.lib oleaut32.lib /subsystem:windows /out:.\gvim.exe

!ELSEIF  "$(CFG)" == "Vim - Win32 Debug gvim OLE"

# PROP Use_Debug_Libraries 1
# PROP Output_Dir .\oleDbg
# PROP Intermediate_Dir .\oleDbg

INTDIR=.\oleDbg
VIM=gvimd
EXTRAS="$(INTDIR)/if_ole.obj" "$(INTDIR)/vim.res" "$(INTDIR)/gui.obj" "$(INTDIR)/gui_w32.obj" "$(INTDIR)/gui_beval.obj" "$(INTDIR)/os_w32exe.obj"

CPP_PROJ=$(CPP_PROJ) /Zi /Od /D "_DEBUG" /D "FEAT_GUI_W32" /D "DYNAMIC_GETTEXT" /D "FEAT_OLE" /Fd.\oleDbg/ /Fo.\oleDbg/
# ADD CPP            /Zi /Od /D "_DEBUG" /D "FEAT_GUI_W32" /D "DYNAMIC_GETTEXT" /D "FEAT_OLE" /Fd.\oleDbg/ /Fo.\oleDbg/

RSC_PROJ=$(RSC_PROJ) /I .\oleDbg /d "_DEBUG" /d "FEAT_OLE" /fo.\oleDbg\vim.res
# ADD RSC            /I .\oleDbg /d "_DEBUG" /d "FEAT_OLE" /fo.\oleDbg\vim.res

LINK32_FLAGS=$(LINK32_FLAGS) libcd.lib oleaut32.lib /subsystem:windows /debug /profile /pdb:.\oleDbg/gvimd.pdb -debug:full -debugtype:cv,fixup /map:.\oleDbg\gvimd.map /out:.\gvimd.exe
# ADD LINK32                 libcd.lib oleaut32.lib /subsystem:windows /debug /profile /pdb:.\oleDbg/gvimd.pdb -debug:full -debugtype:cv,fixup /map:.\oleDbg\gvimd.map /out:.\gvimd.exe


!ELSEIF  "$(CFG)" == "Vim - Win32 Release gvim"

# PROP Use_Debug_Libraries 0
# PROP Output_Dir .\gRel
# PROP Intermediate_Dir .\gRel

INTDIR=.\gRel
VIM=gvim
EXTRAS="$(INTDIR)/vim.res" "$(INTDIR)/gui.obj" "$(INTDIR)/gui_w32.obj" "$(INTDIR)/gui_beval.obj" "$(INTDIR)/os_w32exe.obj"

CPP_PROJ=$(CPP_PROJ) /Zi /O2 /D "NDEBUG" /D "FEAT_GUI_W32" /Fd.\gRel/ /Fo.\gRel/
# ADD CPP            /Zi /O2 /D "NDEBUG" /D "FEAT_GUI_W32" /Fd.\gRel/ /Fo.\gRel/

RSC_PROJ=$(RSC_PROJ) /d "NDEBUG" /fo.\gRel\vim.res
# ADD RSC            /d "NDEBUG" /fo.\gRel\vim.res

LINK32_FLAGS=$(LINK32_FLAGS) /pdb:.\gRel/gvim.pdb -debug:full -debugtype:cv,fixup /map:.\oleDbg\gvim.map libc.lib /subsystem:windows /out:.\gvim.exe
# ADD LINK32                 /pdb:.\gRel/gvim.pdb -debug:full -debugtype:cv,fixup /map:.\oleDbg\gvim.map libc.lib /subsystem:windows /out:.\gvim.exe

!ELSEIF  "$(CFG)" == "Vim - Win32 Debug gvim"

# PROP Use_Debug_Libraries 1
# PROP Output_Dir .\gDbg
# PROP Intermediate_Dir .\gDbg

INTDIR=.\gDbg
VIM=gvimd
EXTRAS="$(INTDIR)/vim.res" "$(INTDIR)/gui.obj" "$(INTDIR)/gui_w32.obj" "$(INTDIR)/gui_beval.obj" "$(INTDIR)/os_w32exe.obj"

CPP_PROJ=$(CPP_PROJ) /Zi /Od /D "_DEBUG" /D "FEAT_GUI_W32" /Fd.\gDbg/ /Fo.\gDbg/
# ADD CPP            /Zi /Od /D "_DEBUG" /D "FEAT_GUI_W32" /Fd.\gDbg/ /Fo.\gDbg/

RSC_PROJ=$(RSC_PROJ) /d "_DEBUG" /fo.\gDbg\vim.res
# ADD RSC            /d "_DEBUG" /fo.\gDbg\vim.res

LINK32_FLAGS=$(LINK32_FLAGS) libcd.lib /subsystem:windows /debug /profile /pdb:.\gDbg/gvimd.pdb -debug:full -debugtype:cv,fixup /map:.\gDbg\gvimd.map /out:.\gvimd.exe
# ADD LINK32                 libcd.lib /subsystem:windows /debug /profile /pdb:.\gDbg/gvimd.pdb -debug:full -debugtype:cv,fixup /map:.\gDbg\gvimd.map /out:.\gvimd.exe

!ELSEIF  "$(CFG)" == "Vim - Win32 Release vim"

# PROP Use_Debug_Libraries 0
# PROP Output_Dir .\Rel
# PROP Intermediate_Dir .\Rel

INTDIR=.\Rel
VIM=vim
EXTRAS=

CPP_PROJ=$(CPP_PROJ) /Zi /O2 /D "NDEBUG" /Fd.\Rel/ /Fo.\Rel/
# ADD CPP            /Zi /O2 /D "NDEBUG" /Fd.\Rel/ /Fo.\Rel/

LINK32_FLAGS=$(LINK32_FLAGS) /pdb:.\Rel/vim.pdb -debug:full -debugtype:cv,fixup /map:.\oleDbg\vim.map libc.lib /subsystem:console /out:.\vim.exe
# ADD LINK32                 /pdb:.\Rel/vim.pdb -debug:full -debugtype:cv,fixup /map:.\oleDbg\vim.map libc.lib /subsystem:console /out:.\vim.exe

!ELSEIF  "$(CFG)" == "Vim - Win32 Debug vim"

# PROP Use_Debug_Libraries 1
# PROP Output_Dir .\Dbg
# PROP Intermediate_Dir .\Dbg

INTDIR=.\Dbg
VIM=vimd
EXTRAS=

CPP_PROJ=$(CPP_PROJ) /Zi /Od /D "_DEBUG" /Fd.\Dbg/ /Fo.\Dbg/
# ADD CPP            /Zi /Od /D "_DEBUG" /Fd.\Dbg/ /Fo.\Dbg/

LINK32_FLAGS=$(LINK32_FLAGS) libcd.lib /subsystem:console /debug /profile /pdb:.\Dbg/vimd.pdb -debug:full -debugtype:cv,fixup /map:.\Dbg/vimd.map /out:.\vimd.exe
# ADD LINK32                 libcd.lib /subsystem:console /debug /profile /pdb:.\Dbg/vimd.pdb -debug:full -debugtype:cv,fixup /map:.\Dbg/vimd.map /out:.\vimd.exe

!ENDIF

ALL : .\$(VIM).exe vimrun.exe install.exe uninstal.exe xxd/xxd.exe GvimExt/gvimext.dll

LINK32_OBJS= \
	$(EXTRAS) \
	"$(INTDIR)/arabic.obj" \
	"$(INTDIR)/blowfish.obj" \
	"$(INTDIR)/buffer.obj" \
	"$(INTDIR)/charset.obj" \
	"$(INTDIR)/crypt.obj" \
	"$(INTDIR)/crypt_zip.obj" \
	"$(INTDIR)/dict.obj" \