18

I couldn't find anything useful on the MSDN for this case. Using Dependency Walker, in the module list, I see a mixed usage of Console and GUI.

Does this have an impact when compiling a DLL?

2 Answers 2

15

This option only has an effect on applications (exe), not on libraries(dll).

Its documentation says:

The /SUBSYSTEM option specifies the environment for the executable.

The choice of subsystem affects the entry point symbol (or entry point function) that the linker will select.

This does not affect libraries, which have their own (optional) entry point.

Additional information following CyberShadow's comment: The subsystem field itself seems to be ignored when a DLL is loaded. This article about CSRSS says (emphasis mine):

Furthermore, each process is associated with one, certain subsystem; this property is being set by the linker (during the compilation process), and resides in the following PE structure field: [...]

6
  • 1
    This flag affect ANY image file. Take a look at many \system32*.dll (e.g. NTDLL.DLL which is tagged with the /SUBSYSTEM:CONSOLE)
    – mox
    Commented Jul 30, 2012 at 7:49
  • 1
    @mox, all image files contain this flag, but it does not affect the entry point of libraries. As you can see, ntdll.dll can be loaded in the address space of both console and Windows executables without ill effects. Commented Jul 30, 2012 at 7:52
  • 1
    This flag has an impact on how the Windows Loader will handle the image. It documents the expectations of the image in regard of the Win32 subsystem (which is implemented in CSRSS.EXE).
    – mox
    Commented Jul 30, 2012 at 7:53
  • 3
    Frédéric, your answer appears to be based on an incomplete understanding of the question, and you do not seem to understand mox's comments either. Every PE file (EXE, DLL, SYS...) has a header field (specifically, IMAGE_OPTIONAL_HEADER.Subsystem), which apparently can take over a dozen meaningful distinct values (see the IMAGE_SUBSYSTEM_* enum). The /SUBSYSTEM linker option does more than choose an entry point, it also populates the Subsystem field in the header. The question was: when loading a DLL, does the Subsystem field in the DLL itself have any effect? Commented Sep 9, 2014 at 8:23
  • 1
    @CyberShadow, it's been a while since I posted this, so it's not easy to go back to my reasoning at the time. If I understand your comment correctly, the questioner wants to know if the subsystem header field has an impact when loading a DLL. From the information I could gather, that's not the case. I updated my answer accordingly, please follow up if I missed the point again. Commented Sep 9, 2014 at 8:49
5

My below reply is just some findings.

I tried to create below types of project within VS2015:

  • Win32 console app project
  • Win32 DLL project
  • Win32 Windows app project

Below are their complete linking options:

Win32 console app project

/OUT:"C:\Temp\ConsoleApplication3\Debug\ConsoleApplication3.exe" /MANIFEST /NXCOMPAT /PDB:"C:\Temp\ConsoleApplication3\Debug\ConsoleApplication3.pdb" /DYNAMICBASE "kernel32.lib" "user32.lib" "gdi32.lib" "winspool.lib" "comdlg32.lib" "advapi32.lib" "shell32.lib" "ole32.lib" "oleaut32.lib" "uuid.lib" "odbc32.lib" "odbccp32.lib" /DEBUG /MACHINE:X86 /INCREMENTAL /PGD:"C:\Temp\ConsoleApplication3\Debug\ConsoleApplication3.pgd" /SUBSYSTEM:CONSOLE /MANIFESTUAC:"level='asInvoker' uiAccess='false'" /ManifestFile:"Debug\ConsoleApplication3.exe.intermediate.manifest" /ERRORREPORT:PROMPT /NOLOGO /TLBID:1

Win32 DLL project

/OUT:"C:\Temp\ConsoleApplication3\Debug\Win32DLLProject1.dll" /MANIFEST /NXCOMPAT /PDB:"C:\Temp\ConsoleApplication3\Debug\Win32DLLProject1.pdb" /DYNAMICBASE "kernel32.lib" "user32.lib" "gdi32.lib" "winspool.lib" "comdlg32.lib" "advapi32.lib" "shell32.lib" "ole32.lib" "oleaut32.lib" "uuid.lib" "odbc32.lib" "odbccp32.lib" /IMPLIB:"C:\Temp\ConsoleApplication3\Debug\Win32DLLProject1.lib" /DEBUG /DLL /MACHINE:X86 /INCREMENTAL /PGD:"C:\Temp\ConsoleApplication3\Debug\Win32DLLProject1.pgd" /SUBSYSTEM:WINDOWS /MANIFESTUAC:"level='asInvoker' uiAccess='false'" /ManifestFile:"Debug\Win32DLLProject1.dll.intermediate.manifest" /ERRORREPORT:PROMPT /NOLOGO /TLBID:1

Win32 Windows app project

/OUT:"C:\Temp\ConsoleApplication3\Debug\Win32WindowsProject1.exe" /MANIFEST /NXCOMPAT /PDB:"C:\Temp\ConsoleApplication3\Debug\Win32WindowsProject1.pdb" /DYNAMICBASE "kernel32.lib" "user32.lib" "gdi32.lib" "winspool.lib" "comdlg32.lib" "advapi32.lib" "shell32.lib" "ole32.lib" "oleaut32.lib" "uuid.lib" "odbc32.lib" "odbccp32.lib" /DEBUG /MACHINE:X86 /INCREMENTAL /PGD:"C:\Temp\ConsoleApplication3\Debug\Win32WindowsProject1.pgd" /SUBSYSTEM:WINDOWS /MANIFESTUAC:"level='asInvoker' uiAccess='false'" /ManifestFile:"Debug\Win32WindowsProject1.exe.intermediate.manifest" /ERRORREPORT:PROMPT /NOLOGO /TLBID:1

So we can see, for a /DLL, /SUBSYSTEM:WINDOWS is defined.

Then I tried to build a DLL with 3 different SUBSYSTEM values:

  • CONSOLE
  • WINDOWS
  • NOT SET

There are other values as well, but I can only build successfully with the above 3. Other values will lead to linking errors, which means some external symbols are needed.

The full list of possible SUBSYSTEM values is:

enter image description here

You can use the CFF Explorer to inspect the PE/COFF binaries.

The SUBSYSTEM header field locates at the file offset 0x14C of a PE/COFF file. It is part of the Optional Header.

/DLL /SUBSYESTEM:CONSOLE

enter image description here

/DLL /SUBSYESTEM:WINDOWS

enter image description here

/DLL and no /SUBSYESTEM option (by selecting NOT SET in VS2015 project properties page

enter image description here

Interestingly, the NOT SET and WINDOWS values lead to the same content in the binary header.

And I compared the whole binary of the 3 DLLs. It seems the rest of the binaries are all the same, except for some timestamp and debug info.

This is just some fact I found. How /SUBSYSTEM option affects the binary behavior depends on how the loader interprets this field.

In one of the projects I participated in, the /SUBSYSTEM:CONSOLE and /DLL are used together, which is different from the default combination for a DLL project. But it seems nothing bad happens. So I agree with @Frédéric Hamidi that this flag has no functional impact to a DLL.

Not the answer you're looking for? Browse other questions tagged or ask your own question.