Skip to content

Instantly share code, notes, and snippets.

@ASkyeye
Forked from odzhan/crt.c
Created April 29, 2025 12:27
Show Gist options
  • Select an option

  • Save ASkyeye/a7c5dce7bbff2e8c2a48b0d4860c824b to your computer and use it in GitHub Desktop.

Select an option

Save ASkyeye/a7c5dce7bbff2e8c2a48b0d4860c824b to your computer and use it in GitHub Desktop.

Revisions

  1. @odzhan odzhan revised this gist Apr 27, 2025. 1 changed file with 11 additions and 0 deletions.
    11 changes: 11 additions & 0 deletions hello.c
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,11 @@

    // cl /D_NO_CRT_STDIO_INLINE /Os /O1 /GS- hello.c crt.c /link /nodefaultlib /subsystem:console msvcrt.lib kernel32.lib

    #include <stdio.h>

    int main(int argc, char *argv[]) {
    for (int i=0; i<argc; i++) {
    printf("argv[%i]: %s\n", i, argv[i]);
    }
    return 0;
    }
  2. @odzhan odzhan created this gist Apr 27, 2025.
    51 changes: 51 additions & 0 deletions crt.c
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,51 @@
    /**
    Compile with your C console project.
    */
    #include <stdio.h>
    #include <windows.h>

    #define __UNKNOWN_APP 0
    #define __CONSOLE_APP 1
    #define __GUI_APP 2

    int main(int, char **, char **);
    int wmain(int, wchar_t **, wchar_t **);

    typedef void (__cdecl * new_handler) ();

    typedef struct _startupinfo_t {
    int newmode;
    new_handler newh;
    } _startupinfo;

    int __getmainargs(int *argc, char ***argv, char ***penv, int glob, _startupinfo *info);
    int __wgetmainargs(int *argc, wchar_t ***argv, wchar_t ***penv, int glob, _startupinfo *info);

    #ifndef _UNICODE
    void mainCRTStartup(void)
    #else
    void wmainCRTStartup(void)
    #endif
    {
    _startupinfo si = {0};
    int argc, ret;

    __set_app_type(__CONSOLE_APP);

    #ifndef _UNICODE
    char **argv = NULL;
    char **envp = NULL;

    __getmainargs(&argc, &argv, &envp, 0, &si);
    ret = main(argc, argv, envp);
    #else
    wchar_t **argv = NULL;
    wchar_t **wenvp = NULL;

    __wgetmainargs(&argc, &wargv, &wenvp, 0, &si);
    ret = wmain(argc, wargv, wenvp);
    #endif

    ExitProcess(ret);
    }

    71 changes: 71 additions & 0 deletions dll2def.py
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,71 @@
    #!/usr/bin/env python3
    """
    dll2def.py - Create a module-definition (.def) file from a Windows DLL.
    Usage
    -----
    python dll2def.py library.dll [optional_output.def]
    The script writes a .def file next to the DLL (or to the explicitly
    supplied output path) and prints a short summary.
    Requires
    --------
    pip install pefile
    """
    from __future__ import annotations
    import argparse
    import sys
    from pathlib import Path
    import pefile


    def build_def_text(dll_path: Path) -> str:
    """Return the complete .def file text for *dll_path*."""
    pe = pefile.PE(dll_path.as_posix(), fast_load=True)
    pe.parse_data_directories(directories=[pefile.DIRECTORY_ENTRY['IMAGE_DIRECTORY_ENTRY_EXPORT']])

    if not hasattr(pe, 'DIRECTORY_ENTRY_EXPORT'):
    raise ValueError(f"'{dll_path.name}' has no export table.")

    lines: list[str] = []
    lines.append(f'LIBRARY "{dll_path.name}"')
    lines.append('EXPORTS')

    for sym in pe.DIRECTORY_ENTRY_EXPORT.symbols:
    # Symbol names can be None (export-by-ordinal only)
    name = sym.name.decode(errors='replace') if sym.name else f'#{sym.ordinal}'
    lines.append(f' {name}')

    # A final newline keeps MSVC's LIB.EXE happy
    return '\n'.join(lines) + '\n'


    def parse_args(argv: list[str]) -> argparse.Namespace:
    p = argparse.ArgumentParser(description="Generate a .def file from a DLL's export table.")
    p.add_argument('dll', type=Path, help='Path to the input DLL')
    p.add_argument('out', nargs='?', type=Path,
    help='Optional .def output path (default: DLL name with .def extension)')
    return p.parse_args(argv)


    def main(argv: list[str] | None = None) -> None:
    args = parse_args(argv or sys.argv[1:])

    dll_path: Path = args.dll.expanduser().resolve()
    if not dll_path.is_file():
    sys.exit(f"Error: '{dll_path}' is not a file.")

    out_path: Path = (args.out or dll_path.with_suffix('.def')).expanduser().resolve()

    try:
    def_text = build_def_text(dll_path)
    except Exception as exc:
    sys.exit(f"Failed to read exports: {exc}")

    out_path.write_text(def_text, encoding='utf-8')
    print(f"Wrote {out_path} ({len(def_text.splitlines()) - 2} exports)")


    if __name__ == '__main__':
    main()