Create a spec file

From ReactOS Wiki
Revision as of 22:49, 31 July 2015 by Learn more (talk | contribs) (imports -> exports)
Jump to: navigation, search

Prerequisites

  • Python 2.7 (and at least the ability to read it, and modify the code shown here to suit your needs).
  • pefile (Very simple / nice to use PE file library, if you don't have it, install with: pip install pefile)
  • A building checkout of ROS (Example source is in R:/src)
  • A dll to base the stubs on (Stored in d:/dll/w2k3/vssapi.dll for this example)

Getting started

As a first step, let's get accustomed to pefile a bit, and examine the exports from our target dll. The usage examples of pefile show how to iterate exports.

Let's apply that (and don't forget to change the path to your local copy of the dll):

import pefile

pe = pefile.PE('d:/dll/w2k3/vssapi.dll')
for entry in pe.DIRECTORY_ENTRY_EXPORT.symbols:
    print entry.ordinal, entry.name

This lists all functions exported, and their ordinal. A small snippet of the output:

8 ??0CVssJetWriter@@QAE@XZ
9 ??0CVssWriter@@QAE@XZ
10 ??1CVssJetWriter@@UAE@XZ
11 ??1CVssWriter@@UAE@XZ
12 ?AreComponentsSelected@CVssWriter@@IBG_NXZ
.. snip ..

If you are wondering about the '?' and '@' in the function names: These are so called 'decorated' or 'mangled' exports, which means that the compiler encoded extra info in the function name.

All right, we have a list of all exports, so let's continue to the next step.

Adding a new dll with CMake

  1. Navigate to R:/src/win32
  2. Create a new folder, and name it the same as your target dll (vssapi in the example, substitute with your target).
  3. Open R:/src/win32/CMakeLists.txt with a texteditor, and add a line: add_subdirectory(vssapi) (and again, substitute it). This tells cmake to also include the directory named vssapi when looking for stuff to include.
  4. Open the new folder (R:/src/win32/vssapi), and create a new (empty) file: R:/src/win32/vssapi/vssapi.spec (where you again substitute vssapi with your target).
  5. Create another file: R:/src/win32/vssapi/CMakeLists.txt, with content:

include_directories(${REACTOS_SOURCE_DIR}/include/reactos/wine)
add_definitions(-D__WINESRC__)
spec2def(vssapi.dll vssapi.spec ADD_IMPORTLIB)

list(APPEND SOURCE
    ${CMAKE_CURRENT_BINARY_DIR}/vssapi_stubs.c)

add_library(vssapi SHARED
    ${SOURCE}
    ${CMAKE_CURRENT_BINARY_DIR}/vssapi.def)

set_module_type(vssapi win32dll)
target_link_libraries(vssapi wine)
add_importlibs(vssapi msvcrt kernel32 ntdll)
add_cd_file(TARGET vssapi DESTINATION reactos/system32 FOR all)

And of course, substitute every occurrence of vssapi with your dll name. This file tells cmake to use the vssapi.spec file to create a dll, and that the dll should be stored in reactos/system32. (And some more stuff, but that's a story for another day.)

Now we should be able to build an empty dll, so re-run cmake (just building anything else should work, cmake will detect the change in r:/src/dll/win32/CMakeLists.txt).

After re-running cmake, there should be a new target: vssapi.dll, so let's build that.

Filling in the blanks

So, to recap: we can build an empty dll, and we can list all exports from a dll. Let's combine this to build a dll with stubbed functions!

Looking at a few .spec files now, the format seems to be very simple: [ordinal or @] [stub|stdcall] [functionname] So all we have to do is print 'stub' inbetween the ordinal and name we already printed, and that should be it (see The finished script for the result)! Now we can paste the output from the script in the .spec file, rebuild the dll and we have a stubbed dll!

The finished script


import pefile

pe = pefile.PE('d:/dll/w2k3/vssapi.dll')
for entry in pe.DIRECTORY_ENTRY_EXPORT.symbols:
    print entry.ordinal, 'stub', entry.name