Alef/nocdkey – User

From Bohemia Interactive Community
Jump to navigation Jump to search
mNo edit summary
m (Text replacement - "\[ *((ftp|http)s?:\/\/[^ ]+)([^{])=([^}])([^ ]+)" to "[$1$3{{=}}$4$5")
 
(34 intermediate revisions by 4 users not shown)
Line 1: Line 1:
'''nocdkey here doesn't mean you can play illegal copies with this plugin!'''<br>
{{Feature|important|"nocdkey" here doesn't mean you can play illegal copies with this plugin!}}
=== What is this? ===
This is a plugin to avoid the problems described {{Link|link= http://dev-heaven.net/issues/3445|text= here (#3445 at CIT)}}.


A fast way to setup MP missions is to run two ArmA games on the same computer. Let's call the first Editor and the second Client.
=== Gamespy ===
Editor run the mission editor, selected clicking on Multiplayer -> New -> Edit/New.
The CD key check will be skipped at least if the name for the gamespy servers are not found, or resolved. It doesn't simply mean you can force a different IP, like ''127.0.0.1'', editing your <tt>c:\windows\system32\drivers\etc\hosts</tt>.
Client can now join it selecting Multiplayer -> LAN or Remote wiht IP 127.0.0.1. It will see Editor in edit mode.
As Editor click on preview to run the mission, a PBO is create on the fly (__cur_mp.pbo) for Client to be available.
Both now enter the usual lobby and choose the slot they want. They play the mission, and when they leave back to the lobby, they can choose to run it again or go back. Editor in this case to the mission editor, Client to the multiplayer screen or 'Wait for host'.


In order to avoid to click the menus, command line arguments are available.
=== ws2_32.dll ===
For Editor<pre>
To connect to the Internet, like all the other programs on Windows, ArmA uses a DLL called <tt>ws2_32.dll</tt>, that is a file installed in <tt>c:\windows\system32</tt>. If you put another file with the same name in the ArmA installation directory, or in the <tt>beta</tt> folder if you run the beta, ArmA will use that instead of the Windows one. It is roughly the same like Armalib from Kegetys or JayArmA2lib, which uses <tt>dsound.dll</tt> to inject custom code in the ArmA process address space.<br>
\ArmA\arma.exe  -host
I've modified a program found online (see the [[#Links|links]] below), that intercept the functions ArmA does to connect other computers. One of these functions is <tt>[http://msdn.microsoft.com/en-us/library/ms738524(VS.85).aspx gethostbyname]</tt>, which is used to obtain an IP address given a name.<br>
</pre>
==== How it works ====
For Client<pre>
When ArmA asks for host names in the domain <tt>gamespy.com</tt>, in order to check for duplicated CD keys, if the address it's found and valid, the check will happens. If ''not'', the server will get the message <tt>"No challenge value was received from the master server."</tt>. My <tt>ws2_32.dll</tt> let the latter happens, but only if you use <b><tt>-nocdkey</tt></b> together with <b><tt>-host</tt></b> on the command line.
\ArmA\arma.exe -connect=localhost
==== Drawbacks ====
</pre>
The DLL will intercept all of the network functions made by ArmA. All of them, apart the one above, add an overhead for this to work. This overhead consists of a single <tt>jmp</tt> instruction without stack management (nacked), which may add a delay equal to one memory fetch when it is not in cpu cache.
It is suggested to add<pre>
-window -nosplash -world=empty -nopause
</pre>to speed up things and run safe from alt-tabbing.


This plugin simulate what you usually can do just dropping your connection to the internet using ''[[ArmA:_Startup_Parameters#Network_Options| -host]]'' mode.
{{Feature|important|This should be something legally doable, because BI already provided the way to work without checking for duplicated CD keys both on dedicated server and in hosted server when Gamespy host is not reachable. No reverse-engineering work has been done on network packets nor for in-memory or on-disk executable images.}}
You can't use ''kickduplicate=0'' because the ''-config=server.cfg'' doesn't get read in ''-host'' mode.


[http://www.ofpec.com/forum/index.php?topic=32619.0 OFPEC beta]
== Links ==
[http://www.xfire.com/video/4d907/ Xfire video]
* Download available at {{Link|link= http://dev-heaven.net/projects/alef-projects/files|text= dev-heaven.net}}
This is a file called ''ws2_32.dll'' to put in the same ''arma.exe'' directory, and get enabled using ''-nocdkey'' and ''-host'' arguments on the command line.
* OFPEC beta [http://www.ofpec.com/forum/index.php?topic{{=}}32619.0 request]
It will intercept the host name resolution for gamespy service, returning a "not found" answer. This is the same effect you can obtain disconnecting the network cable.
* Xfire [http://www.xfire.com/video/4d907/ video] showing the procedure
 
* Original code: [http://www.codeguru.com/forum/archive/index.php/t-386875.html codeguru.com]
==How to run 2 ArmAs on the same PC==
Need a crafted ''ws2_32.dll'', which returns ''WSAHOST_NOT_FOUND'' in ''gethostbyname()'' for ''armedass.master.gamespy.com'' or ''armedass.available.gamespy.com'' if -nocdkey is given on the server (-host) command line.
<pre>
Editor/Server:
\ArmA\arma.exe -window -nosplash -world=empty -nopause -host -nokey
 
Client:
\ArmA\arma.exe -window -nosplash -world=empty -nopause -connect=localhost
</pre>
 
The server will get the message "No challenge value was received from the master server."
 
Will post on OFPEC for beta, if someone interested, and on BI forum.
==How it works?==
To connect to the Internet, like all the other programs on Windows, ArmA uses a DLL called ws2_32.dll, that is a file installed in C:\Windows\System32. If you put another file with the same name in the ArmA installation directory, ArmA will use that instead of the Windows one. It is like the Armalib from Kegetys (OFPWatch too?).
I've modified a program, that intercept the functions ArmA does to connect other computers. One of these functions is gethostbyname, which usually is used to obtain an internet address given a name, like www.ofpec.com returns 85.17.58.182. Now, if ArmA asks for gamespy.com to check for duplicated CD keys, if the address it's found and valid, the check will happens.
You can usually avoid this in server.cfg (-config) with kickduplicate=0, BUT if you run arma.exe with -host, you can't avoid the check. server.cfg only works with -server, the dedicated one.
Why run arma.exe with -host? Because you will jump directly at start in the Multiplayer page "Create Game", and choose a mission to edit. There, you can edit your mission, your scripts, etc. Then, you can run another arma.exe to connect the former (on LAN, server "localhost" or "127.0.0.1") . On this you will see the multiplayer page (LAN) with your server in state "Editing". As you click "Preview" in the editor arma, the other game can join. On abort, both return the mutiplayer lobby. In this way you speed up a lot the testing of multiplayer game.


== Source ==
You get the full source in the distributed archive. This is the working code extracted from there:
<pre>
<pre>
struct hostent* FAR(__stdcall h_gethostbyname)(__in const char *name) {
struct hostent* FAR(__stdcall h_gethostbyname)(__in const char *name) {
     using namespace std;
     using namespace std;
     static const string master("armedass.master.gamespy.com"), available("armedass.available.gamespy.com");
     static const string gamespy("gamespy.com");
     static const wstring mhost(L"-host"), mnocdkey(L"-nocdkey");
     static const wstring mhost(L"-host"), mnocdkey(L"-nocdkey");
     static bool host=false, nocdkey=false, argschecked=false;
     static bool host=false, nocdkey=false, argschecked=false;
     struct hostent* FAR rc = 0;
     struct hostent* FAR rc = 0;
     if (!argschecked) {
     if (!argschecked) {
argschecked=true;
        argschecked=true;
LPWSTR *szArglist;
        LPWSTR *szArglist;
int nArgs;
        int nArgs;
szArglist = CommandLineToArgvW(GetCommandLineW(), &nArgs);
        szArglist = CommandLineToArgvW(GetCommandLineW(), &nArgs);
if( NULL != szArglist ) for(int i=0; i<nArgs ; ++i) {
        if( NULL != szArglist ) for(int i=0; i<nArgs ; ++i) {
if (!host)    host=(mhost.compare(szArglist[i]) == 0);  
                if (!host)    host=(mhost == szArglist[i]);  
if (!nocdkey) nocdkey=(mnocdkey.compare(szArglist[i]) == 0);
                if (!nocdkey) nocdkey=(mnocdkey == szArglist[i]);
}
        }
LocalFree(szArglist);
        LocalFree(szArglist);
     }
     }
     if (host && nocdkey && name && (master.compare(name) == 0 || available.compare(name) == 0) ) {
    const string sname=name;
p_WSASetLastError(WSAHOST_NOT_FOUND);
     if (host && nocdkey && name && (
        string::npos != sname.find( gamespy, sname.length() - gamespy.length())
    )) {
        p_WSASetLastError(WSAHOST_NOT_FOUND);
     } else {
     } else {
rc=p_gethostbyname(name);
        rc=p_gethostbyname(name);
     }
     }
     return rc;
     return rc;
}
}
</pre>
</pre>
 
Where ''p_'' is the original DLL function entry point and ''h_'' the overloaded one.
References:
http://forum.koaxia.com/index.php?PHPSESSID=8c74b13cfe75e2b293e4825c7e7985e5&topic=3099.0
http://www.codeguru.com/forum/archive/index.php/t-386875.html

Latest revision as of 17:20, 28 April 2023

"nocdkey" here doesn't mean you can play illegal copies with this plugin!

What is this?

This is a plugin to avoid the problems described here (#3445 at CIT) (dead link).

Gamespy

The CD key check will be skipped at least if the name for the gamespy servers are not found, or resolved. It doesn't simply mean you can force a different IP, like 127.0.0.1, editing your c:\windows\system32\drivers\etc\hosts.

ws2_32.dll

To connect to the Internet, like all the other programs on Windows, ArmA uses a DLL called ws2_32.dll, that is a file installed in c:\windows\system32. If you put another file with the same name in the ArmA installation directory, or in the beta folder if you run the beta, ArmA will use that instead of the Windows one. It is roughly the same like Armalib from Kegetys or JayArmA2lib, which uses dsound.dll to inject custom code in the ArmA process address space.
I've modified a program found online (see the links below), that intercept the functions ArmA does to connect other computers. One of these functions is gethostbyname, which is used to obtain an IP address given a name.

How it works

When ArmA asks for host names in the domain gamespy.com, in order to check for duplicated CD keys, if the address it's found and valid, the check will happens. If not, the server will get the message "No challenge value was received from the master server.". My ws2_32.dll let the latter happens, but only if you use -nocdkey together with -host on the command line.

Drawbacks

The DLL will intercept all of the network functions made by ArmA. All of them, apart the one above, add an overhead for this to work. This overhead consists of a single jmp instruction without stack management (nacked), which may add a delay equal to one memory fetch when it is not in cpu cache.

This should be something legally doable, because BI already provided the way to work without checking for duplicated CD keys both on dedicated server and in hosted server when Gamespy host is not reachable. No reverse-engineering work has been done on network packets nor for in-memory or on-disk executable images.

Links

  • Download available at dev-heaven.net (dead link)
  • OFPEC beta request
  • Xfire video showing the procedure
  • Original code: codeguru.com

Source

You get the full source in the distributed archive. This is the working code extracted from there:

struct hostent* FAR(__stdcall h_gethostbyname)(__in const char *name) {
    using namespace std;
    static const string gamespy("gamespy.com");
    static const wstring mhost(L"-host"), mnocdkey(L"-nocdkey");
    static bool host=false, nocdkey=false, argschecked=false;
    struct hostent* FAR rc = 0;
    if (!argschecked) {
        argschecked=true;
        LPWSTR *szArglist;
        int nArgs;
        szArglist = CommandLineToArgvW(GetCommandLineW(), &nArgs);
        if( NULL != szArglist ) for(int i=0; i<nArgs ; ++i) {
                if (!host)    host=(mhost == szArglist[i]); 
                if (!nocdkey) nocdkey=(mnocdkey == szArglist[i]);
        }
        LocalFree(szArglist);
    }
    const string sname=name;
    if (host && nocdkey && name && (
        string::npos != sname.find( gamespy, sname.length() - gamespy.length())
    )) {
        p_WSASetLastError(WSAHOST_NOT_FOUND);
    } else {
        rc=p_gethostbyname(name);
    }
    return rc;
}

Where p_ is the original DLL function entry point and h_ the overloaded one.