Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Custom error message when Visual Studio distributable package is not installed on Windows #48

Open
kubo opened this issue Nov 23, 2017 · 1 comment

Comments

@kubo
Copy link

kubo commented Nov 23, 2017

How about custom error message when Visual Studio distributable package is not installed?
IMO, oracle/node-oracledb#404 (comment) should be checked in ODPI-C.

When GetLastError() returns ERROR_MOD_NOT_FOUND(The specified module could not be found), do the following.

  1. Search OCI.DLL in the following directories in this order:
    1. Executable directory (Get the full path of the executable by GetModuleFileName(NULL, buf, sizeof(buf)) and truncate the file name.)
    2. Current directory
    3. each directory in the environment variable PATH.
  2. If OCI.DLL is not found, use the message from FormatMessage().
  3. If OCI.DLL is found, get the bit of the DLL (see the function below) and skip if it isn't same with the executable.
  4. If step 3 passes, get import DLL files (see the function below) and get the DLL whose name is 'MSVCR*.DLL'.
  5. Call LoadLibrary with the 'MSVCR*.DLL' at step 4.
  6. If step 5 fails, map the 'MSVCR*.DLL' name to VS distributable package name and create a custom error message.

The following is a sample function which prints bit and dependent DLL files.
It is easy to customize this to fit this issue's need.

// link dbghelp.lib also
#include <dbghelp.h>

static void print_import_dlls(const char *name)
{
    HANDLE hFile = CreateFile(name, GENERIC_READ, FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE,
                              NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
    HANDLE hFileMapping = NULL;
    void *base = NULL;
    if (hFile == INVALID_HANDLE_VALUE) {
        printf("failed to open: %s\n", name);
        return;
    }
    hFileMapping = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL);
    if (hFileMapping == NULL) {
        printf("failed to create file mapping: %s\n", name);
        goto cleanup;
    }
    base = MapViewOfFile(hFileMapping, FILE_MAP_READ, 0, 0, 0);
    if (base == NULL) {
        printf("failed to map file: %s\n", name);
        goto cleanup;
    }
    IMAGE_NT_HEADERS *nt_hdr = ImageNtHeader(base);
    if (nt_hdr == NULL) {
        printf("not executable nor DLL: %s\n", name);
        goto cleanup;
    }

    printf("%s (%s bit):\n", name, nt_hdr->FileHeader.Machine == IMAGE_FILE_MACHINE_I386 ? "32" : "64");
    ULONG uSize = 0;
    IMAGE_IMPORT_DESCRIPTOR *desc = (IMAGE_IMPORT_DESCRIPTOR *)ImageDirectoryEntryToDataEx(base, FALSE, IMAGE_DIRECTORY_ENTRY_IMPORT, &uSize, NULL);

    while (desc->Characteristics != 0) {
        char *name = (char*)ImageRvaToVa(nt_hdr, base, desc->Name, NULL);
        printf("  %s\n", name);
        desc++;
    }
cleanup:
    if (base != NULL) {
        UnmapViewOfFile(base);
    }
    if (hFileMapping != NULL) {
        CloseHandle(hFileMapping);
    }
    CloseHandle(hFile);
}
@anthony-tuininga
Copy link
Member

Thanks, @kubo. Adding this code to ODPI-C does make sense. I've marked this as an enhancement request.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants