0

I am stuck in a tight spot and I need some help with some C++ code. This is my first attempt at doing C++ and it born mostly from necessity at this point.

I am trying (unsuccessfully it feels) to build a native NAN module for Node.JS that will be used by an Electron app on Windows.

I need it to return the WinHttpDetectAutoProxyConfigUrl when the users Proxy configuration is set to Auto Detect.

I have built this exact thing in C# for another application and it works seamlessly in our distributed user BYOD environment. However in this case I do not wish to be dependent on the dot.net framework unnecessarily.

Right know I am at the extent of my knowledge when it comes to C++ as most of my knowledge over the years has thus far been theoretical. I am hoping that someone that actually works in C++ daily can look at my code and help correct the error that is happening.

I have been trying to debug using the “std::cout” in VSCode.

As you can see from the output at the bottom of the image, that some of it appears to be working and the code is dropping into the “Get Auto URL” IF block as expected. However the output is very iritic (“�����”) and nothing like the wpad.dat URL I was expecting to see returned from the wpad protocol implemented by the winhttp.dll.

My Problem: It is as though the result is blank and then the “char buffer[2083];” is being sent to the stdOut and the characters are all encoded wrong.

Any help on this would be very helpful so thanks in advance.

Please see the code below.

main.cpp

#include <nan.h>
#include <Windows.h>
#include <Winhttp.h>
#include <iostream>

#pragma comment(lib, "winhttp.lib")

using namespace std;

// NAN_METHOD is a Nan macro enabling convenient way of creating native node functions.
// It takes a method's name as a param. By C++ convention, I used the Capital cased name.
NAN_METHOD(AutoProxyConfigUrl) {

    cout << "AutoProxyConfigUrl" << "\n"; 

    v8::Isolate* isolate = info.GetIsolate(); // args.GetIsolate();

    LPWSTR strConfigUrl = NULL;
    WINHTTP_CURRENT_USER_IE_PROXY_CONFIG MyProxyConfig;

    if(!WinHttpGetIEProxyConfigForCurrentUser(&MyProxyConfig))
    { 
        //check the error DWORD Err = GetLastError(); 
        DWORD Err = GetLastError(); 
        cout << "WinHttpGetIEProxyConfigForCurrentUser failed with the following error number: " << Err << "\n";
        switch (Err) 
        {
            case ERROR_FILE_NOT_FOUND: 
            cout << "The error is ERROR_FILE_NOT_FOUND" << "\n"; 
            break; 
            case ERROR_WINHTTP_INTERNAL_ERROR:
            cout << "ERROR_WINHTTP_INTERNAL_ERROR" << "\n"; 
            break; 
            case ERROR_NOT_ENOUGH_MEMORY:
            cout << "ERROR_NOT_ENOUGH_MEMORY" << "\n"; 
            break; 
            default: 
            cout << "Look up error in header file." << "\n"; 
            break; 
        }//end switch 

        //TODO this might not be a good idea but it is worth trying
        strConfigUrl = L"http://wpad/wpad.dat"; //Default to Fallback wpad 

    }//end if 
    else 
    { 
        //no error so check the proxy settings and free any strings 
        cout << "Auto Detect is: " << MyProxyConfig.fAutoDetect <<  "\n"; 

        if(MyProxyConfig.fAutoDetect){

             cout << "Get Auto URL" <<  "\n"; 

            if (!WinHttpDetectAutoProxyConfigUrl(WINHTTP_AUTO_DETECT_TYPE_DHCP | WINHTTP_AUTO_DETECT_TYPE_DNS_A, &strConfigUrl))
            {
                cout << "Error getting URL" <<  "\n"; 

                //This error message is not necessarily a problem and can be ignored if you are using direct connection. you get this error if you are having direct connection.
                //check the error DWORD Err = GetLastError(); 
                DWORD Err = GetLastError(); 
                if (ERROR_WINHTTP_AUTODETECTION_FAILED == Err)
                {
                    strConfigUrl = L"http://wpad/wpad.dat"; //Default to Fallback wpad 
                }

                //TODO work out what to do with the other errors

            }
        }

        if(NULL != MyProxyConfig.lpszAutoConfigUrl) 
        { 
            wcout << "AutoConfigURL (MyProxyConfig.lpszAutoConfigUrl) is: " << MyProxyConfig.lpszAutoConfigUrl << "\n"; 
            GlobalFree(MyProxyConfig.lpszAutoConfigUrl);
        }

        if(NULL != MyProxyConfig.lpszProxy) 
        { 
            wcout << "AutoConfigURL (MyProxyConfig.lpszProxy) is: " << MyProxyConfig.lpszProxy << "\n";
            GlobalFree(MyProxyConfig.lpszProxy);
         }

        if(NULL != MyProxyConfig.lpszProxyBypass) 
        {
            wcout << "AutoConfigURL is: " << MyProxyConfig.lpszProxyBypass << "\n";                      
            GlobalFree(MyProxyConfig.lpszProxyBypass); 
        }
    }//end else 

     //cout << "strConfigUrl" << strConfigUrl << "\n"; 

    char buffer[2083];
    wcstombs( buffer, strConfigUrl, wcslen(strConfigUrl) ); // Need wcslen to compute the length of the string

    // convert it to string
    std::string returnUrl(buffer);  

    // Create an instance of V8's String type
    auto message = Nan::New(returnUrl).ToLocalChecked();

    // 'info' is a macro's "implicit" parameter - it's a bridge object between C++ and JavaScript runtimes
    // You would use info to both extract the parameters passed to a function as well as set the return value.
    info.GetReturnValue().Set(message);

    if(strConfigUrl)
        GlobalFree(strConfigUrl);

}   

// Module initialization logic
NAN_MODULE_INIT(Initialize) {
    // Export the `Hello` function (equivalent to `export function Hello (...)` in JS)
    NAN_EXPORT(target, AutoProxyConfigUrl);
}

// Create the module called "addon" and initialize it with `Initialize` function (created with NAN_MODULE_INIT macro)
NODE_MODULE(proxyautodetect, Initialize);

main.js

// note that the compiled addon is placed under following path
//const {AutoProxyConfigUrl} = require('./build/Release/proxyautodetect.node');
const {AutoProxyConfigUrl} = require('./build/Debug/proxyautodetect.node');

// `Hello` function returns a string, so we have to console.log it!
console.log(AutoProxyConfigUrl());

Build and Run output:

C:\Code\Work\wpad-auto-detect>if not defined npm_config_node_gyp (node "C:\Program Files\nodejs\node_modules\npm\node_modules\npm-lifecycle\node-gyp-bin\\..\..\node_modules\node-gyp\bin\node-gyp.js" rebuild --debug )  else (node "C:\Program Files\nodejs\node_modules\npm\node_modules\node-gyp\bin\node-gyp.js" rebuild --debug )
Building the projects in this solution one at a time. To enable parallel build, please add the "/m" switch.
  main.cpp
  win_delay_load_hook.cc
     Creating library C:\Code\Work\wpad-auto-detect\build\Debug\proxyautodetect.lib and object C:\Code\Work\wpad-auto-detect\build\Debug\proxyautodet
  ect.exp
  proxyautodetect.vcxproj -> C:\Code\Work\wpad-auto-detect\build\Debug\\proxyautodetect.node
PS C:\Code\Work\wpad-auto-detect> npm start

> proxyautodetect@1.0.0 start C:\Code\Work\wpad-auto-detect
> node main.js

AutoProxyConfigUrl
Auto Detect is: 1
Get Auto URL
"
"��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������1��J╗
PS C:\Code\Work\wpad-auto-detect>

Image of code output

INK
  • 13
  • 5
  • I have not worked out the empty quotes but I have been able to get rid of the buffer print out to screen with a Substr. – INK Nov 25 '18 at 22:56

1 Answers1

0

I did a sort of Trim

   int urlLen = wcslen(strConfigUrl) ;

#if DEBUG
    cout << "strConfigUrl wcslen : " << urlLen << "\n";      
#endif 

    char buffer[2083]; //This is the max length a URL can be in IE
    wcstombs( buffer, strConfigUrl, wcslen(strConfigUrl) ); // Need wcslen to compute the length of the string

    // convert it to string
    std::string returnUrl(buffer);  

    // Create an instance of V8's String type and Return only the Length needed so kind of Trim the extra char
    auto message = Nan::New(returnUrl.substr(0, urlLen)).ToLocalChecked();
INK
  • 13
  • 5