[TUT] Making A Simple Steam Emulator

1337

Full Member
This Is Hard And Very Long I Suggest You Get A Drink Or Something :)


This document contains details of how to build a very simple steam emulator, it only emulates a couple of functions, but as you will see, could be expanded to do more. It is a good way of writing an emulator, as you can replace the original steam.dll code functions as and when you want.

Before I start, please note that I have been using this method for my own purposes for a very long time (when I wrote UGL in fact) yet never saw the need to "release" anything as it only does (in its simplest form as detailed here) what any decent crack can do in a few bytes. It is very similar to CueSteamEmu, though a lot simpler to understand from a teaching perspective.

First, you will need C++ - If you don't have it, then do one of the following:

Get Visual Studio 2005

Get Visual C++ 2005 express edition - Note the express edition cannot compile Win32 code "out of the box". You will need to follow instructions here: http://msdn.microsoft.com/vstudio/express/visualc/usingpsdk/ on how to do this, but this involves having to also download the Microsoft Platform SDK. As this is nearly 500mb, It may be a lot less hassle to get VS2005 in the long run! Wink
I quickly built this tutorial with Visual Studio 2005 to check my syntax.

Start a New project and create a windows console application with the name "Steam", making sure that you select "dll" as the application type and that you tick the "Export Symbols" box.

You will now have a basic C++ dll project, however, before we do anything it is important that our project contains exactly the same resources as the original steam.dll file, so use your favourite resource editor to create a steam.res file from the original steam.dll and then make sure you include it in your project.


Next we need to forward all the steam.dll functions that are called through our dll onto the genuine steam.dll file, so we don't break anything.

We can do this really easily using the #Pragma directive. For the current steam.dll functions, we need to forward the following functions:

Note that for the community beta version of steam, there are 156 ordinals, so you will need to dump a clean list. The text in this post will be edited only for the current release version of steam.

Code:
#pragma comment(linker, "/export:CreateInterface=ValveSteam.CreateInterface,@1")
#pragma comment(linker, "/export:InternalSteamNumClientsConnectedToEngine=ValveSteam.InternalSteam NumClientsConnectedToEngine,@2")
#pragma comment(linker, "/export:InternalSteamShouldShutdownEngine2=ValveSteam.InternalSteamShould ShutdownEngine2,@3")
#pragma comment(linker, "/export:SteamAbortCall=ValveSteam.SteamAbortCall,@4")
#pragma comment(linker, "/export:SteamAbortOngoingUserIDTicketValidation=ValveSteam.SteamAbortOngo ingUserIDTicketValidation,@5")
#pragma comment(linker, "/export:SteamAckSubscriptionReceipt=ValveSteam.SteamAckSubscriptionReceip t,@6")
#pragma comment(linker, "/export:SteamBlockingCall=ValveSteam.SteamBlockingCall,@7")
#pragma comment(linker, "/export:SteamChangeAccountName=ValveSteam.SteamChangeAccountName,@8")
#pragma comment(linker, "/export:SteamChangeEmailAddress=ValveSteam.SteamChangeEmailAddress,@9")
#pragma comment(linker, "/export:SteamChangeForgottenPassword=ValveSteam.SteamChangeForgottenPassw ord,@10")
#pragma comment(linker, "/export:SteamChangeOfflineStatus=ValveSteam.SteamChangeOfflineStatus,@11" )
#pragma comment(linker, "/export:SteamChangePassword=ValveSteam.SteamChangePassword,@12")
#pragma comment(linker, "/export:SteamChangePersonalQA=ValveSteam.SteamChangePersonalQA,@13")
#pragma comment(linker, "/export:SteamCleanup=ValveSteam.SteamCleanup,@14")
#pragma comment(linker, "/export:SteamClearError=ValveSteam.SteamClearError,@15")
#pragma comment(linker, "/export:SteamCloseFile=ValveSteam.SteamCloseFile,@16")
#pragma comment(linker, "/export:SteamCreateAccount=ValveSteam.SteamCreateAccount,@17")
#pragma comment(linker, "/export:SteamCreateCachePreloaders=ValveSteam.SteamCreateCachePreloaders, @18")
#pragma comment(linker, "/export:SteamCreateLogContext=ValveSteam.SteamCreateLogContext,@19")
#pragma comment(linker, "/export:SteamDecryptDataForThisMachine=ValveSteam.SteamDecryptDataForThis Machine,@20")
#pragma comment(linker, "/export:SteamDeleteAccount=ValveSteam.SteamDeleteAccount,@21")
#pragma comment(linker, "/export:SteamEncryptDataForThisMachine=ValveSteam.SteamEncryptDataForThis Machine,@22")
#pragma comment(linker, "/export:SteamEnumerateApp=ValveSteam.SteamEnumerateApp,@23")
#pragma comment(linker, "/export:SteamEnumerateAppDependency=ValveSteam.SteamEnumerateAppDependenc y,@24")
#pragma comment(linker, "/export:SteamEnumerateAppIcon=ValveSteam.SteamEnumerateAppIcon,@25")
#pragma comment(linker, "/export:SteamEnumerateAppLaunchOption=ValveSteam.SteamEnumerateAppLaunchO ption,@26")
#pragma comment(linker, "/export:SteamEnumerateAppVersion=ValveSteam.SteamEnumerateAppVersion,@27" )
#pragma comment(linker, "/export:SteamEnumerateSubscription=ValveSteam.SteamEnumerateSubscription, @28")
#pragma comment(linker, "/export:SteamEnumerateSubscriptionDiscount=ValveSteam.SteamEnumerateSubsc riptionDiscount,@29")
#pragma comment(linker, "/export:SteamEnumerateSubscriptionDiscountQualifier=ValveSteam.SteamEnume rateSubscriptionDiscountQualifier,@30")
#pragma comment(linker, "/export:SteamFindApp=ValveSteam.SteamFindApp,@31")
#pragma comment(linker, "/export:SteamFindClose=ValveSteam.SteamFindClose,@32")
#pragma comment(linker, "/export:SteamFindFirst=ValveSteam.SteamFindFirst,@33")
#pragma comment(linker, "/export:SteamFindNext=ValveSteam.SteamFindNext,@34")
#pragma comment(linker, "/export:SteamFindServersGetErrorString=ValveSteam.SteamFindServersGetErro rString,@35")
#pragma comment(linker, "/export:SteamFindServersIterateServer=ValveSteam.SteamFindServersIterateS erver,@36")
#pragma comment(linker, "/export:SteamFindServersNumServers=ValveSteam.SteamFindServersNumServers, @37")
#pragma comment(linker, "/export:SteamFlushCache=ValveSteam.SteamFlushCache,@38")
#pragma comment(linker, "/export:SteamFlushFile=ValveSteam.SteamFlushFile,@39")
#pragma comment(linker, "/export:SteamForgetAllHints=ValveSteam.SteamForgetAllHints,@40")
#pragma comment(linker, "/export:SteamGenerateSuggestedAccountNames=ValveSteam.SteamGenerateSugges tedAccountNames,@41")
#pragma comment(linker, "/export:SteamGetAccountStatus=ValveSteam.SteamGetAccountStatus,@42")
#pragma comment(linker, "/export:SteamGetAppCacheSize=ValveSteam.SteamGetAppCacheSize,@43")
#pragma comment(linker, "/export:SteamGetAppDependencies=ValveSteam.SteamGetAppDependencies,@44")
#pragma comment(linker, "/export:SteamGetAppDir=ValveSteam.SteamGetAppDir,@45")
#pragma comment(linker, "/export:SteamGetAppIds=ValveSteam.SteamGetAppIds,@46")
#pragma comment(linker, "/export:SteamGetAppPurchaseCountry=ValveSteam.SteamGetAppPurchaseCountry, @47")
#pragma comment(linker, "/export:SteamGetAppStats=ValveSteam.SteamGetAppStats,@48")
#pragma comment(linker, "/export:SteamGetAppUpdateStats=ValveSteam.SteamGetAppUpdateStats,@49")
#pragma comment(linker, "/export:SteamGetAppUserDefinedInfo=ValveSteam.SteamGetAppUserDefinedInfo, @50")
#pragma comment(linker, "/export:SteamGetAppUserDefinedRecord=ValveSteam.SteamGetAppUserDefinedRec ord,@51")
#pragma comment(linker, "/export:SteamGetCacheDecryptionKey=ValveSteam.SteamGetCacheDecryptionKey, @52")
#pragma comment(linker, "/export:SteamGetCacheDefaultDirectory=ValveSteam.SteamGetCacheDefaultDire ctory,@53")
#pragma comment(linker, "/export:SteamGetCacheFilePath=ValveSteam.SteamGetCacheFilePath,@54")
#pragma comment(linker, "/export:SteamGetContentServerInfo=ValveSteam.SteamGetContentServerInfo,@5 5")
#pragma comment(linker, "/export:SteamGetCurrentEmailAddress=ValveSteam.SteamGetCurrentEmailAddres s,@56")
#pragma comment(linker, "/export:SteamGetEncryptedNewValveCDKey=ValveSteam.SteamGetEncryptedNewVal veCDKey,@57")
#pragma comment(linker, "/export:SteamGetEncryptedUserIDTicket=ValveSteam.SteamGetEncryptedUserIDT icket,@58")
#pragma comment(linker, "/export:SteamGetEncryptionKeyToSendToNewClient=ValveSteam.SteamGetEncrypt ionKeyToSendToNewClient,@59")
#pragma comment(linker, "/export:SteamGetLocalClientVersion=ValveSteam.SteamGetLocalClientVersion, @60")
#pragma comment(linker, "/export:SteamGetLocalFileCopy=ValveSteam.SteamGetLocalFileCopy,@61")
#pragma comment(linker, "/export:SteamGetNumAccountsWithEmailAddress=ValveSteam.SteamGetNumAccount sWithEmailAddress,@62")
#pragma comment(linker, "/export:SteamGetOfflineStatus=ValveSteam.SteamGetOfflineStatus,@63")
#pragma comment(linker, "/export:SteamGetSponsorUrl=ValveSteam.SteamGetSponsorUrl,@64")
#pragma comment(linker, "/export:SteamGetSubscriptionExtendedInfo=ValveSteam.SteamGetSubscriptionE xtendedInfo,@65")
#pragma comment(linker, "/export:SteamGetSubscriptionIds=ValveSteam.SteamGetSubscriptionIds,@66")
#pragma comment(linker, "/export:SteamGetSubscriptionPurchaseCountry=ValveSteam.SteamGetSubscripti onPurchaseCountry,@67")
#pragma comment(linker, "/export:SteamGetSubscriptionReceipt=ValveSteam.SteamGetSubscriptionReceip t,@68")
#pragma comment(linker, "/export:SteamGetSubscriptionStats=ValveSteam.SteamGetSubscriptionStats,@6 9")
#pragma comment(linker, "/export:SteamGetTotalUpdateStats=ValveSteam.SteamGetTotalUpdateStats,@70" )
#pragma comment(linker, "/export:SteamGetUser=ValveSteam.SteamGetUser,@71")
#pragma comment(linker, "/export:SteamGetUserType=ValveSteam.SteamGetUserType,@72")
#pragma comment(linker, "/export:SteamGetVersion=ValveSteam.SteamGetVersion,@73")
#pragma comment(linker, "/export:SteamGetc=ValveSteam.SteamGetc,@74")
#pragma comment(linker, "/export:SteamHintResourceNeed=ValveSteam.SteamHintResourceNeed,@75")
#pragma comment(linker, "/export:SteamInitializeUserIDTicketValidator=ValveSteam.SteamInitializeUs erIDTicketValidator,@76")
#pragma comment(linker, "/export:SteamInsertAppDependency=ValveSteam.SteamInsertAppDependency,@77" )
#pragma comment(linker, "/export:SteamIsAccountNameInUse=ValveSteam.SteamIsAccountNameInUse,@78")
#pragma comment(linker, "/export:SteamIsAppSubscribed=ValveSteam.SteamIsAppSubscribed,@79")
#pragma comment(linker, "/export:SteamIsCacheLoadingEnabled=ValveSteam.SteamIsCacheLoadingEnabled, @80")
#pragma comment(linker, "/export:SteamIsFileImmediatelyAvailable=ValveSteam.SteamIsFileImmediately Available,@81")
#pragma comment(linker, "/export:SteamIsFileNeededByCache=ValveSteam.SteamIsFileNeededByCache,@82" )
#pragma comment(linker, "/export:SteamIsLoggedIn=ValveSteam.SteamIsLoggedIn,@83")
#pragma comment(linker, "/export:SteamIsSecureComputer=ValveSteam.SteamIsSecureComputer,@84")
#pragma comment(linker, "/export:SteamIsSubscribed=ValveSteam.SteamIsSubscribed,@85")
#pragma comment(linker, "/export:SteamLaunchApp=ValveSteam.SteamLaunchApp,@86")
#pragma comment(linker, "/export:SteamLoadCacheFromDir=ValveSteam.SteamLoadCacheFromDir,@87")
#pragma comment(linker, "/export:SteamLoadFileToCache=ValveSteam.SteamLoadFileToCache,@88")
#pragma comment(linker, "/export:SteamLog=ValveSteam.SteamLog,@89")
#pragma comment(linker, "/export:SteamLogResourceLoadFinished=ValveSteam.SteamLogResourceLoadFinis hed,@90")
#pragma comment(linker, "/export:SteamLogResourceLoadStarted=ValveSteam.SteamLogResourceLoadStarte d,@91")
#pragma comment(linker, "/export:SteamLogin=ValveSteam.SteamLogin,@92")
#pragma comment(linker, "/export:SteamLogout=ValveSteam.SteamLogout,@93")
#pragma comment(linker, "/export:SteamMountAppFilesystem=ValveSteam.SteamMountAppFilesystem,@94")
#pragma comment(linker, "/export:SteamMountFilesystem=ValveSteam.SteamMountFilesystem,@95")
#pragma comment(linker, "/export:SteamMoveApp=ValveSteam.SteamMoveApp,@96")
#pragma comment(linker, "/export:SteamNumAppsRunning=ValveSteam.SteamNumAppsRunning,@97")
#pragma comment(linker, "/export:SteamOpenFile=ValveSteam.SteamOpenFile,@98")
#pragma comment(linker, "/export:SteamOpenFileEx=ValveSteam.SteamOpenFileEx,@99")
#pragma comment(linker, "/export:SteamOpenTmpFile=ValveSteam.SteamOpenTmpFile,@100")
#pragma comment(linker, "/export:SteamOptionalCleanUpAfterClientHasDisconnected=ValveSteam.SteamOp tionalCleanUpAfterClientHasDisconnected,@101")
#pragma comment(linker, "/export:SteamPauseCachePreloading=ValveSteam.SteamPauseCachePreloading,@1 02")
#pragma comment(linker, "/export:SteamPrintFile=ValveSteam.SteamPrintFile,@103")
#pragma comment(linker, "/export:SteamProcessCall=ValveSteam.SteamProcessCall,@104")
#pragma comment(linker, "/export:SteamProcessOngoingUserIDTicketValidation=ValveSteam.SteamProcess OngoingUserIDTicketValidation,@105")
#pragma comment(linker, "/export:SteamPutc=ValveSteam.SteamPutc,@106")
#pragma comment(linker, "/export:SteamReadFile=ValveSteam.SteamReadFile,@107")
#pragma comment(linker, "/export:SteamRefreshAccountInfo=ValveSteam.SteamRefreshAccountInfo,@108")
#pragma comment(linker, "/export:SteamRefreshAccountInfoEx=ValveSteam.SteamRefreshAccountInfoEx,@1 09")
#pragma comment(linker, "/export:SteamRefreshLogin=ValveSteam.SteamRefreshLogin,@110")
#pragma comment(linker, "/export:SteamRefreshMinimumFootprintFiles=ValveSteam.SteamRefreshMinimumF ootprintFiles,@111")
#pragma comment(linker, "/export:SteamRemoveAppDependency=ValveSteam.SteamRemoveAppDependency,@112 ")
#pragma comment(linker, "/export:SteamRepairOrDecryptCaches=ValveSteam.SteamRepairOrDecryptCaches, @113")
#pragma comment(linker, "/export:SteamRequestAccountsByCdKeyEmail=ValveSteam.SteamRequestAccountsB yCdKeyEmail,@114")
#pragma comment(linker, "/export:SteamRequestAccountsByEmailAddressEmail=ValveSteam.SteamRequestAc countsByEmailAddressEmail,@115")
#pragma comment(linker, "/export:SteamRequestEmailAddressVerificationEmail=ValveSteam.SteamRequest EmailAddressVerificationEmail,@116")
#pragma comment(linker, "/export:SteamRequestForgottenPasswordEmail=ValveSteam.SteamRequestForgott enPasswordEmail,@117")
#pragma comment(linker, "/export:SteamResumeCachePreloading=ValveSteam.SteamResumeCachePreloading, @118")
#pragma comment(linker, "/export:SteamSeekFile=ValveSteam.SteamSeekFile,@119")
#pragma comment(linker, "/export:SteamSetAppCacheSize=ValveSteam.SteamSetAppCacheSize,@120")
#pragma comment(linker, "/export:SteamSetAppVersion=ValveSteam.SteamSetAppVersion,@121")
#pragma comment(linker, "/export:SteamSetCacheDefaultDirectory=ValveSteam.SteamSetCacheDefaultDire ctory,@122")
#pragma comment(linker, "/export:SteamSetMaxStallCount=ValveSteam.SteamSetMaxStallCount,@123")
#pragma comment(linker, "/export:SteamSetNotificationCallback=ValveSteam.SteamSetNotificationCallb ack,@124")
#pragma comment(linker, "/export:SteamSetUser=ValveSteam.SteamSetUser,@125")
#pragma comment(linker, "/export:SteamSetvBuf=ValveSteam.SteamSetvBuf,@126")
#pragma comment(linker, "/export:SteamShutdownEngine=ValveSteam.SteamShutdownEngine,@127")
#pragma comment(linker, "/export:SteamShutdownUserIDTicketValidator=ValveSteam.SteamShutdownUserID TicketValidator,@128")
#pragma comment(linker, "/export:SteamSizeFile=ValveSteam.SteamSizeFile,@129")
#pragma comment(linker, "/export:SteamStartEngine=ValveSteam.SteamStartEngine,@130")
#pragma comment(linker, "/export:SteamStartLoadingCache=ValveSteam.SteamStartLoadingCache,@131")
#pragma comment(linker, "/export:SteamStartValidatingNewValveCDKey=ValveSteam.SteamStartValidating NewValveCDKey,@132")
#pragma comment(linker, "/export:SteamStartValidatingUserIDTicket=ValveSteam.SteamStartValidatingU serIDTicket,@133")
#pragma comment(linker, "/export:SteamStartup=ValveSteam.SteamStartup,@134")
#pragma comment(linker, "/export:SteamStat=ValveSteam.SteamStat,@135")
#pragma comment(linker, "/export:SteamStopLoadingCache=ValveSteam.SteamStopLoadingCache,@136")
#pragma comment(linker, "/export:SteamSubscribe=ValveSteam.SteamSubscribe,@137")
#pragma comment(linker, "/export:SteamTellFile=ValveSteam.SteamTellFile,@138")
#pragma comment(linker, "/export:SteamUninstall=ValveSteam.SteamUninstall,@139")
#pragma comment(linker, "/export:SteamUnmountAppFilesystem=ValveSteam.SteamUnmountAppFilesystem,@1 40")
#pragma comment(linker, "/export:SteamUnmountFilesystem=ValveSteam.SteamUnmountFilesystem,@141")
#pragma comment(linker, "/export:SteamUnsubscribe=ValveSteam.SteamUnsubscribe,@142")
#pragma comment(linker, "/export:SteamUpdateAccountBillingInfo=ValveSteam.SteamUpdateAccountBillin gInfo,@143")
#pragma comment(linker, "/export:SteamUpdateSubscriptionBillingInfo=ValveSteam.SteamUpdateSubscrip tionBillingInfo,@144")
#pragma comment(linker, "/export:SteamVerifyEmailAddress=ValveSteam.SteamVerifyEmailAddress,@145")
#pragma comment(linker, "/export:SteamVerifyPassword=ValveSteam.SteamVerifyPassword,@146")
#pragma comment(linker, "/export:SteamWaitForAppReadyToLaunch=ValveSteam.SteamWaitForAppReadyToLau nch,@147")
#pragma comment(linker, "/export:SteamWaitForResources=ValveSteam.SteamWaitForResources,@148")
#pragma comment(linker, "/export:SteamWeakVerifyNewValveCDKey=ValveSteam.SteamWeakVerifyNewValveCD Key,@149")
#pragma comment(linker, "/export:SteamWriteFile=ValveSteam.SteamWriteFile,@150")
#pragma comment(linker, "/export:SteamWriteMiniDumpFromAssert=ValveSteam.SteamWriteMiniDumpFromAss ert,@151")
#pragma comment(linker, "/export:SteamWriteMiniDumpSetComment=ValveSteam.SteamWriteMiniDumpSetComm ent,@152")
#pragma comment(linker, "/export:SteamWriteMiniDumpUsingExceptionInfo=ValveSteam.SteamWriteMiniDum pUsingExceptionInfo,@153")
#pragma comment(linker, "/export:SteamWriteMiniDumpUsingExceptionInfoWithBuildId=ValveSteam.SteamW riteMiniDumpUsingExceptionInfoWithBuildId,@154")
#pragma comment(linker, "/export:__f=ValveSteam._f,@155")

You can see which functions a dll exports in a number of different tools (dumpbin, PEExplorer) and can grab a list to use in your dll. I suggest you try some out and discover your favourite because if Steam updates, then you will need to rebuild this list, extract the latest resources and recompile your dll.

The #pragma comment statement used in this context allows our dll to export the functions above as though they were its own. On calling, our dll will simply call the real steam.dll function and return its results. Note that in the above, I have renamed the real steam.dll to ValveSteam.dll, and also note that we have specified export ordinal numbers that match exactly the ordinals of the original steam.dll function by function.

Now, go to your Steam.h header file and delete everything in it (we don't need it), before pasting in all of the #pragma comment statements from above.

Next, go to your Steam.cpp file and delete all the #ifdef statements within it, also delete anything that appears after the DllMain function, as again, we don't need any of it.

You now have a steam.dll stub that is capable of calling all the original steam.dll functions. If you build it and copy it into your steam folder, after renaming your original Steam.dll file to ValveSteam.dll, then steam will behave exactly as it used to, we haven't changed anything, we've just made all the steam calls go through our own code first.

Now, some of you will be thinking, well, surely we can do things to all of those functions then, like hijack the whole function if need be, and you'd be right Smile

Edit your Steam.h file and add the following line before the #pragma comments

Code:
#include "SteamEmulation.h"

create a new header file called SteamEmulation.h and add to it the following code (we will expand on this later).

Code:
#include "SteamCommon.h"

Create another header file called SteamCommon.h and paste in the following code, this code is contained in most steam solutions and contains all the required types and structures.

Code:
//*********** (C) Copyright 2002 Valve, L.L.C. All rights reserved. ***********
//
// The copyright to the contents herein is the property of Valve, L.L.C.
// The contents may be used and/or copied only with the written permission of
// Valve, L.L.C., or in accordance with the terms and conditions stipulated in
// the agreement/contract under which the contents have been supplied.
//
//*********************************************************************** ******
//
// Contents:
//
// SteamUserID types.
//
// This file is distributed to Steam application developers.
//
// Authors:
//
// Target restrictions:
//
// Tool restrictions:
//
// Things to do:
//
//
//
//*********************************************************************** ******

#ifndef INCLUDED_STEAM_COMMON_STEAMCOMMON_H
#define INCLUDED_STEAM_COMMON_STEAMCOMMON_H

#pragma once

#ifdef __cplusplus
extern "C"
{
#endif

/* Applications should not define STEAM_EXPORTS. */

#if defined ( WIN32 )

#ifdef STEAM_EXPORTS
#define STEAM_API __declspec(dllexport)
#else
#define STEAM_API __declspec(dllimport)
#endif

#define STEAM_CALL __cdecl

#else

#define STEAM_API /* */
#define STEAM_CALL /* */

#endif

/************************************************************************ ******
**
** Exported macros and constants
**
************************************************************************* *****/

#define STEAM_USING_FILESYSTEM (0x00000001)
#define STEAM_USING_LOGGING (0x00000002)
#define STEAM_USING_USERID (0x00000004)
#define STEAM_USING_ACCOUNT (0x00000008)
#define STEAM_USING_ALL (0x0000000f)
#define STEAM_MAX_PATH (255)
#define STEAM_QUESTION_MAXLEN (255)
#define STEAM_SALT_SIZE (8)

#define STEAM_CARD_NUMBER_SIZE (16)
#define STEAM_CARD_HOLDERNAME_SIZE (80)
#define STEAM_CARD_EXPYEAR_SIZE (4)
#define STEAM_CARD_EXPMONTH_SIZE (2)
#define STEAM_CARD_CVV2_SIZE (10)
#define STEAM_BILLING_ADDRESS1_SIZE (80)
#define STEAM_BILLING_ADDRESS2_SIZE (80)
#define STEAM_BILLING_CITY_SIZE (80)
#define STEAM_BILLING_ZIP_SIZE (10)
#define STEAM_BILLING_STATE_SIZE (40)
#define STEAM_BILLING_COUNTRY_SIZE (40)
#define STEAM_BILLING_PHONE_SIZE (20)
#define STEAM_TYPE_OF_PROOF_OF_PURCHASE_SIZE (20)
#define STEAM_PROOF_OF_PURCHASE_TOKEN_SIZE (200)
#define STEAM_EXTERNAL_ACCOUNTNAME_SIZE (80)
#define STEAM_EXTERNAL_ACCOUNTPASSWORD_SIZE (80)

/************************************************************************ ******
**
** Scalar type and enumerated type definitions.
**
************************************************************************* *****/

typedef unsigned int SteamHandle_t;

typedef void * SteamUserIDTicketValidationHandle_t;

typedef unsigned int SteamCallHandle_t;

#if defined(_MSC_VER)
typedef unsigned __int64 SteamUnsigned64_t;
#else
typedef unsigned long long SteamUnsigned64_t;
#endif

typedef enum
{
eSteamSeekMethodSet = 0,
eSteamSeekMethodCur = 1,
eSteamSeekMethodEnd = 2
} ESteamSeekMethod;

typedef enum
{
eSteamBufferMethodFBF = 0,
eSteamBufferMethodNBF = 1
} ESteamBufferMethod;

typedef enum
{
eSteamErrorNone = 0,
eSteamErrorUnknown = 1,
eSteamErrorLibraryNotInitialized = 2,
eSteamErrorLibraryAlreadyInitialized = 3,
eSteamErrorConfig = 4,
eSteamErrorContentServerConnect = 5,
eSteamErrorBadHandle = 6,
eSteamErrorHandlesExhausted = 7,
eSteamErrorBadArg = 8,
eSteamErrorNotFound = 9,
eSteamErrorRead = 10,
eSteamErrorEOF = 11,
eSteamErrorSeek = 12,
eSteamErrorCannotWriteNonUserConfigFile = 13,
eSteamErrorCacheOpen = 14,
eSteamErrorCacheRead = 15,
eSteamErrorCacheCorrupted = 16,
eSteamErrorCacheWrite = 17,
eSteamErrorCacheSession = 18,
eSteamErrorCacheInternal = 19,
eSteamErrorCacheBadApp = 20,
eSteamErrorCacheVersion = 21,
eSteamErrorCacheBadFingerPrint = 22,

eSteamErrorNotFinishedProcessing = 23,
eSteamErrorNothingToDo = 24,
eSteamErrorCorruptEncryptedUserIDTicket = 25,
eSteamErrorSocketLibraryNotInitialized = 26,
eSteamErrorFailedToConnectToUserIDTicketValidationServer = 27,
eSteamErrorBadProtocolVersion = 28,
eSteamErrorReplayedUserIDTicketFromClient = 29,
eSteamErrorReceiveResultBufferTooSmall = 30,
eSteamErrorSendFailed = 31,
eSteamErrorReceiveFailed = 32,
eSteamErrorReplayedReplyFromUserIDTicketValidationServer = 33,
eSteamErrorBadSignatureFromUserIDTicketValidationServer = 34,
eSteamErrorValidationStalledSoAborted = 35,
eSteamErrorInvalidUserIDTicket = 36,
eSteamErrorClientLoginRateTooHigh = 37,
eSteamErrorClientWasNeverValidated = 38,
eSteamErrorInternalSendBufferTooSmall = 39,
eSteamErrorInternalReceiveBufferTooSmall = 40,
eSteamErrorUserTicketExpired = 41,
eSteamErrorCDKeyAlreadyInUseOnAnotherClient = 42,

eSteamErrorNotLoggedIn = 101,
eSteamErrorAlreadyExists = 102,
eSteamErrorAlreadySubscribed = 103,
eSteamErrorNotSubscribed = 104,
eSteamErrorAccessDenied = 105,
eSteamErrorFailedToCreateCacheFile = 106,
eSteamErrorCallStalledSoAborted = 107,
eSteamErrorEngineNotRunning = 108,
eSteamErrorEngineConnectionLost = 109,
eSteamErrorLoginFailed = 110,
eSteamErrorAccountPending = 111,
eSteamErrorCacheWasMissingRetry = 112,
eSteamErrorLocalTimeIncorrect = 113,

eSteamErrorNetwork = 200


} ESteamError;


typedef enum
{
eNoDetailedErrorAvailable,
eStandardCerrno,
eWin32LastError,
eWinSockLastError,
eDetailedPlatformErrorCount
} EDetailedPlatformErrorType;

typedef enum /* Filter elements returned by SteamFind{First,Next} */
{
eSteamFindLocalOnly, /* limit search to local filesystem */
eSteamFindRemoteOnly, /* limit search to remote repository */
eSteamFindAll /* do not limit search (duplicates allowed) */
} ESteamFindFilter;


/************************************************************************ ******
**
** Exported structure and complex type definitions.
**
************************************************************************* *****/


typedef struct
{
ESteamError eSteamError;
EDetailedPlatformErrorType eDetailedErrorType;
int nDetailedErrorCode;
char szDesc[STEAM_MAX_PATH];
} TSteamError;



typedef struct
{
int bIsDir; /* If non-zero, element is a directory; if zero, element is a file */
unsigned int uSizeOrCount; /* If element is a file, this contains size of file in bytes */
int bIsLocal; /* If non-zero, reported item is a standalone element on local filesystem */
char cszName[STEAM_MAX_PATH]; /* Base element name (no path) */
long lLastAccessTime; /* Seconds since 1/1/1970 (like time_t) when element was last accessed */
long lLastModificationTime; /* Seconds since 1/1/1970 (like time_t) when element was last modified */
long lCreationTime; /* Seconds since 1/1/1970 (like time_t) when element was created */
} TSteamElemInfo;


typedef struct
{
unsigned int uNumSubscriptions;
unsigned int uMaxNameChars;
unsigned int uMaxApps;

} TSteamSubscriptionStats;


typedef struct
{
unsigned int AppId;
unsigned int IsRequired;
char szMountName[STEAM_MAX_PATH];
} TSteamAppDependencyInfo;

typedef struct
{
unsigned int uNumApps;
unsigned int uMaxNameChars;
unsigned int uMaxVersionLabelChars;
unsigned int uMaxLaunchOptions;
unsigned int uMaxLaunchOptionDescChars;
unsigned int uMaxLaunchOptionCmdLineChars;
unsigned int uMaxNumIcons;
unsigned int uMaxIconSize;

} TSteamAppStats;

typedef struct
{
char *szLabel;
unsigned int uMaxLabelChars;
unsigned int uVersionId;
int bIsNotAvailable;
} TSteamAppVersion;

typedef struct
{
char *szDesc;
unsigned int uMaxDescChars;
char *szCmdLine;
unsigned int uMaxCmdLineChars;
unsigned int uIndex;
unsigned int uIconIndex;
int bNoDesktopShortcut;
int bNoStartMenuShortcut;
int bIsLongRunningUnattended;

} TSteamAppLaunchOption;


typedef struct
{
char *szName;
unsigned int uMaxNameChars;
char *szLatestVersionLabel;
unsigned int uMaxLatestVersionLabelChars;
char *szCurrentVersionLabel;
unsigned int uMaxCurrentVersionLabelChars;
char *szCacheFile;
unsigned int uMaxCacheFileChars;
unsigned int uId;
unsigned int uLatestVersionId;
unsigned int uCurrentVersionId;
unsigned int uMinCacheFileSizeMB;
unsigned int uMaxCacheFileSizeMB;
unsigned int uNumLaunchOptions;
unsigned int uNumIcons;
unsigned int uNumVersions;
unsigned int numDependencies;
} TSteamApp;

typedef struct
{
char *szName;
unsigned int uMaxNameChars;
unsigned int *puAppIds;
unsigned int uMaxAppIds;
unsigned int uId;
unsigned int uNumApps;
unsigned int uDurationInSeconds;
unsigned int uCostInCents;
unsigned int bIsAutoRenewing;

} TSteamSubscription;

typedef struct TSteamProgress
{
int bValid; // non-zero if call provides progress info
unsigned int uPercentDone; // 0 to 100 if bValid
char szProgress[STEAM_MAX_PATH]; // additional progress info
} TSteamProgress;

typedef enum
{
eSteamNotifyTicketsWillExpire,
eSteamNotifyAccountInfoChanged,
eSteamNotifyContentDescriptionChanged,
eSteamNotifyPleaseShutdown,
eSteamNotifyNewSponsorUrl,
eSteamNotifyAppVersionChanged
} ESteamNotificationCallbackEvent;


typedef void(*SteamNotificationCallback_t)(ESteamNotificationCallbackEvent eEvent, unsigned int nData);


typedef char SteamPersonalQuestion_t[ STEAM_QUESTION_MAXLEN + 1 ];

typedef struct
{
unsigned char uchSalt[STEAM_SALT_SIZE];
} SteamSalt_t;

typedef enum
{
eVisa = 1,
eMaster = 2,
eAmericanExpress = 3,
eDiscover = 4,
eDinnersClub = 5
} ESteamPaymentCardType;

typedef struct
{
ESteamPaymentCardType eCardType;
char szCardNumber[ STEAM_CARD_NUMBER_SIZE +1 ];
char szCardHolderName[ STEAM_CARD_HOLDERNAME_SIZE + 1];
char szCardExpYear[ STEAM_CARD_EXPYEAR_SIZE + 1 ];
char szCardExpMonth[ STEAM_CARD_EXPMONTH_SIZE+ 1 ];
char szCardCVV2[ STEAM_CARD_CVV2_SIZE + 1 ];
char szBillingAddress1[ STEAM_BILLING_ADDRESS1_SIZE + 1 ];
char szBillingAddress2[ STEAM_BILLING_ADDRESS2_SIZE + 1 ];
char szBillingCity[ STEAM_BILLING_CITY_SIZE + 1 ];
char szBillingZip[ STEAM_BILLING_ZIP_SIZE + 1 ];
char szBillingState[ STEAM_BILLING_STATE_SIZE + 1 ];
char szBillingCountry[ STEAM_BILLING_COUNTRY_SIZE + 1 ];
char szBillingPhone[ STEAM_BILLING_PHONE_SIZE + 1 ];
} TSteamPaymentCardInfo;

typedef struct
{
char szTypeOfProofOfPurchase[ STEAM_TYPE_OF_PROOF_OF_PURCHASE_SIZE + 1 ];

// A ProofOfPurchase token is not necessarily a nul-terminated string; it may be binary data
// (perhaps encrypted). Hence we need a length and an array of bytes.
unsigned int uLengthOfBinaryProofOfPurchaseToken;
char cBinaryProofOfPurchaseToken[ STEAM_PROOF_OF_PURCHASE_TOKEN_SIZE + 1 ];
} TSteamPrepurchaseInfo;

typedef struct
{
char szAccountName[ STEAM_EXTERNAL_ACCOUNTNAME_SIZE + 1 ];
char szPassword[ STEAM_EXTERNAL_ACCOUNTPASSWORD_SIZE + 1 ];
} TSteamExternalBillingInfo;

typedef enum
{
ePaymentCardInfo = 1,
ePrepurchasedInfo = 2,
eAccountBillingInfo = 3,
eExternalBillingInfo = 4 // indirect billing via ISP etc (not supported yet)
} ESteamSubscriptionBillingInfoType;

typedef struct
{
ESteamSubscriptionBillingInfoType eBillingInfoType;
union {
TSteamPaymentCardInfo PaymentCardInfo;
TSteamPrepurchaseInfo PrepurchaseInfo;
TSteamExternalBillingInfo ExternalBillingInfo;
char bUseAccountBillingInfo;
};

} TSteamSubscriptionBillingInfo;

typedef struct
{
SteamUnsigned64_t uPhysicalBytesReceived;
} TSteamUpdateStats;

/************************************************************************ ******
**
** More exported constants
**
************************************************************************* *****/


#ifdef __cplusplus

const SteamHandle_t STEAM_INVALID_HANDLE = 0;
const SteamCallHandle_t STEAM_INVALID_CALL_HANDLE = 0;
const SteamUserIDTicketValidationHandle_t STEAM_INACTIVE_USERIDTICKET_VALIDATION_HANDLE = 0;
const unsigned int STEAM_USE_LATEST_VERSION = 0xFFFFFFFF;

#else

#define STEAM_INVALID_HANDLE ((SteamHandle_t)(0))
#define STEAM_INVALID_CALL_HANDLE ((SteamCallHandle_t)(0))
#define STEAM_INACTIVE_USERIDTICKET_VALIDATION_HANDLE ((SteamUserIDTicketValidationHandle_t)(0))
#define STEAM_USE_LATEST_VERSION (0xFFFFFFFFu);

#endif


// Each Steam instance (licensed Steam Service Provider) has a unique SteamInstanceID_t.
//
// Each Steam instance as its own DB of users.
// Each user in the DB has a unique SteamLocalUserID_t (a serial number, with possible
// rare gaps in the sequence).

typedef unsigned short SteamInstanceID_t; // MUST be 16 bits


#if defined ( WIN32 )
typedef unsigned __int64 SteamLocalUserID_t; // MUST be 64 bits
#else
typedef unsigned long long SteamLocalUserID_t; // MUST be 64 bits
#endif


// Applications need to be able to authenticate Steam users from ANY instance.
// So a SteamIDTicket contains SteamGlobalUserID, which is a unique combination of
// instance and user id.

// SteamLocalUserID is an unsigned 64-bit integer.
// For platforms without 64-bit int support, we provide access via a union that splits it into
// high and low unsigned 32-bit ints. Such platforms will only need to compare LocalUserIDs
// for equivalence anyway - not perform arithmetic with them.
typedef struct
{
unsigned int Low32bits;
unsigned int High32bits;
} TSteamSplitLocalUserID;

typedef struct
{
SteamInstanceID_t m_SteamInstanceID;

union
{
SteamLocalUserID_t As64bits;
TSteamSplitLocalUserID Split;
} m_SteamLocalUserID;

} TSteamGlobalUserID;

#ifdef __cplusplus
}
#endif


#endif

What we have done here, is include a file of common steam types and structures to use in our dll. The SteamEmulation header file is where our journey really begins, in here we are going to write code for any functions we want to hijack.

In order for our code to be exported and used instead of the original functions, we need to comment out the #pragma comment for any function we re-write, and add our new functions as exports.

So, create a new module definition file called steam.def and enter the following:

Code:
LIBRARY Steam
EXPORTS

SteamIsAppSubscribed @79
SteamIsSubscribed @85

We define in this file any functions that we want to export in place of the original steam.dll ones, making sure to define them with the same ordinals. Here we are changing the two functions that give us access to all content and allow us to play 3rd party demo content (like popcap games) as the full versions.

These functions are SteamIsSubscribed and SteamIsAppSubscribed, so make sure you comment out those two functions from the #Pragma Comments in the Steam.h file.

So, back to our SteamEmulation.h file and we need to add the following code to it:

.cue has reported later in this thread that all Cafe subscriptions should not return as subscribed as this can lead to problems with registering keys against your account. Cafe subscriptions can also cause the newer steam community beta to lose its community features if they are subscribed. The cafe subscriptions are Subscription ID 4 (Steam Cafe Subscripton) and Subscription ID 67 (VTT Subscription)

Code:
int SteamIsSubscribed(unsigned int uSubscriptionId, int *pbIsSubscribed, int *pbIsReady, TSteamError *pError)
{
switch (uSubscriptionId)
{
case 4: //Cyber Cafe Subscription
*pbIsSubscribed = 0;
break;
case 67: //VTT Subscription
*pbIsSubscribed = 0;
break;
default:
*pbIsSubscribed = 1;
}

*pbIsReady = 1;
return 1;
}

int SteamIsAppSubscribed( unsigned int uAppId, int *pbIsAppSubscribed, int *pbIsReady, TSteamError *pError )
{
*pbIsAppSubscribed = 1;
*pbIsReady = 1;
return 1;
}


Here, We've re-written the steam functions to return the same result regardless of what the queried appid is, they now always return that the subscription to the specified content is valid.


Well, kind of useless, but hopefully interesting and informative to most, and has never failed me through all the steam updates!

Before I go, here's some common problems:

"Unable to find steam.dll entry point" when using the dll
- Your steam.res file is incorrect or missing

The dll exports are wrong (e.g. exports Steam.79 instead of SteamIsAppSubscribed)
- Your def file is incorrect


That's all for now, have fun!
 
Back
Top