how to resolve unresolved externals ?

EDN Admin

Well-known member
Joined
Aug 7, 2010
Messages
12,794
Location
In the Machine
Does anyone know why do I have error LNK1120: 2 unresolved externals? And how I could fix these?

error:
<pre class="prettyprint Error 17 error LNK1120: 2 unresolved externals D:My DocumentsVisual Studio 2010ProjectsserviceDebugservice.exe
Error 16 error LNK2019: unresolved external symbol _CreateEnvironmentBlock@12 referenced in function "bool __cdecl LaunchProcess(unsigned long)" (?LaunchProcess@@YA_NK@Z) D:My DocumentsVisual Studio 2010Projectsserviceservice.obj
Error 15 error LNK2019: unresolved external symbol _DestroyEnvironmentBlock@4 referenced in function "bool __cdecl LaunchProcess(unsigned long)" (?LaunchProcess@@YA_NK@Z) D:My DocumentsVisual Studio 2010Projectsserviceservice.obj
[/code]
<br/>

<br/>

Code:<br/>

<pre class="prettyprint #include <windows.h>
#include <stdio.h>
#include <Wtsapi32.h>
#include <TlHelp32.h>
#include <Userenv.h>
#include <Winbase.h>

PROCESS_INFORMATION ProcessInfo;
static char app_path[MAX_PATH];
bool W2K=0;
int counter=0;
int kickrdp=0;
#define MAXSTRLENGTH 255

BOOL Char2Wchar(WCHAR* pDest, char* pSrc, int nDestStrLen)
{
int nSrcStrLen = 0;
int nOutputBuffLen = 0;
int retcode = 0;

if(pDest == NULL || pSrc == NULL)
{
return FALSE;
}

nSrcStrLen = strlen(pSrc);
if(nSrcStrLen == 0)
{
return FALSE;
}

nDestStrLen = nSrcStrLen;

if (nDestStrLen > MAXSTRLENGTH - 1)
{
return FALSE;
}
memset(pDest,0,sizeof(TCHAR)*nDestStrLen);
nOutputBuffLen = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, pSrc,nSrcStrLen, pDest, nDestStrLen);

if (nOutputBuffLen == 0)
{
retcode = GetLastError();
return FALSE;
}

pDest[nOutputBuffLen] = ;
return TRUE;
}

BOOL SetTBCPrivileges(VOID) {
DWORD dwPID;
HANDLE hProcess;
HANDLE hToken;
LUID Luid;
TOKEN_PRIVILEGES tpDebug;
dwPID = GetCurrentProcessId();
if ((hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwPID)) == NULL) return FALSE;
if (OpenProcessToken(hProcess, TOKEN_ALL_ACCESS, &hToken) == 0) return FALSE;
if ((LookupPrivilegeValue(NULL, SE_TCB_NAME, &Luid)) == 0) return FALSE;
tpDebug.PrivilegeCount = 1;
tpDebug.Privileges[0].Luid = Luid;
tpDebug.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
if ((AdjustTokenPrivileges(hToken, FALSE, &tpDebug, sizeof(tpDebug), NULL, NULL)) == 0) return FALSE;
if (GetLastError() != ERROR_SUCCESS) return FALSE;
CloseHandle(hToken);
CloseHandle(hProcess);
return TRUE;
}

static int pad2()
{

OSVERSIONINFO OSversion;

OSversion.dwOSVersionInfoSize=sizeof(OSVERSIONINFO);

GetVersionEx(&OSversion);
W2K=0;
switch(OSversion.dwPlatformId)
{
case VER_PLATFORM_WIN32_NT:
if(OSversion.dwMajorVersion==5 && OSversion.dwMinorVersion==0)
W2K=1;

}
char exe_file_name[MAX_PATH];
char cmdline[MAX_PATH];
GetModuleFileName(0, exe_file_name, MAX_PATH);

strcpy(app_path, exe_file_name);
return 0;
}

DWORD Find_winlogon(DWORD SessionId)
{

PWTS_PROCESS_INFO pProcessInfo = NULL;
DWORD ProcessCount = 0;
// char szUserName[255];
DWORD Id = -1;

typedef BOOL (WINAPI *pfnWTSEnumerateProcesses)(HANDLE,DWORD,DWORD,PWTS_PROCESS_INFO*,DWORD*);
typedef VOID (WINAPI *pfnWTSFreeMemory)(PVOID);



if (WTSEnumerateProcesses(WTS_CURRENT_SERVER_HANDLE, 0, 1, &pProcessInfo, &ProcessCount))
{
// dump each process description
for (DWORD CurrentProcess = 0; CurrentProcess < ProcessCount; CurrentProcess++)
{

if( _stricmp(pProcessInfo[CurrentProcess].pProcessName, "winlogon.exe") == 0 )
{
if (SessionId==pProcessInfo[CurrentProcess].SessionId)
{
Id = pProcessInfo[CurrentProcess].ProcessId;
break;
}
}
}

WTSFreeMemory(pProcessInfo);
}


return Id;
}

DWORD GetwinlogonPid()
{
//DWORD dwSessionId;
DWORD dwExplorerLogonPid=0;
PROCESSENTRY32 procEntry;

//dwSessionId=0;



HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (hSnap == INVALID_HANDLE_VALUE)
{
return 0 ;
}

procEntry.dwSize = sizeof(PROCESSENTRY32);

if (!Process32First(hSnap, &procEntry))
{
CloseHandle(hSnap);
return 0 ;
}

do
{
if (_stricmp(procEntry.szExeFile, "winlogon.exe") == 0)
{
dwExplorerLogonPid = procEntry.th32ProcessID;
}

} while (Process32Next(hSnap, &procEntry));
CloseHandle(hSnap);
return dwExplorerLogonPid;
}

BOOL get_winlogon_handle(OUT LPHANDLE lphUserToken)
{
BOOL bResult = FALSE;
HANDLE hProcess;
HANDLE hAccessToken = NULL;
HANDLE hTokenThis = NULL;
DWORD ID_session=0;
ID_session=WTSGetActiveConsoleSessionId();
DWORD Id=0;
if (W2K==0) {Id=Find_winlogon(ID_session);}
else{ Id=GetwinlogonPid();}

// fall back to old method if Terminal services is disabled
if (W2K == 0 && Id == -1)
Id=GetwinlogonPid();

#ifdef _DEBUG
char szText[256];
DWORD error=GetLastError();
sprintf(szText," ++++++ Find_winlogon %i %i %dn",ID_session,Id,error);
SetLastError(0);
OutputDebugString(szText);
#endif


hProcess = OpenProcess( PROCESS_ALL_ACCESS, FALSE, Id );
if (hProcess)
{
#ifdef _DEBUG
char szText[256];
DWORD error=GetLastError();
sprintf(szText," ++++++ OpenProcess %i n",hProcess);
SetLastError(0);
OutputDebugString(szText);
#endif

OpenProcessToken(hProcess, TOKEN_ASSIGN_PRIMARY|TOKEN_ALL_ACCESS, &hTokenThis);

#ifdef _DEBUG
error=GetLastError();
sprintf(szText," ++++++ OpenProcessToken %i %in",hTokenThis,error);
SetLastError(0);
OutputDebugString(szText);
#endif
{
bResult = DuplicateTokenEx(hTokenThis, TOKEN_ASSIGN_PRIMARY|TOKEN_ALL_ACCESS,NULL, SecurityImpersonation, TokenPrimary, lphUserToken);
#ifdef _DEBUG
error=GetLastError();
sprintf(szText," ++++++ DuplicateTokenEx %i %i %i %in",hTokenThis,&lphUserToken,error,bResult);
SetLastError(0);
OutputDebugString(szText);
#endif
SetTokenInformation(*lphUserToken, TokenSessionId, &ID_session, sizeof(DWORD));
#ifdef _DEBUG
error=GetLastError();
sprintf(szText," ++++++ SetTokenInformation( %i %i %in",hTokenThis,&lphUserToken,error);
SetLastError(0);
OutputDebugString(szText);
#endif
CloseHandle(hTokenThis);
}
CloseHandle(hProcess);
}
return bResult;
}

BOOL GetSessionUserTokenWin(OUT LPHANDLE lphUserToken)
{
BOOL bResult = FALSE;
HANDLE hImpersonationToken = INVALID_HANDLE_VALUE;
DWORD ID=0;
if (WTSGetActiveConsoleSessionId() != 0){ID=WTSGetActiveConsoleSessionId();}
HANDLE hTokenThis = NULL;

if (lphUserToken != NULL) {
bResult = get_winlogon_handle(lphUserToken);
}
return bResult;
}

typedef BOOLEAN (WINAPI* pWinStationQueryInformationW)(
IN HANDLE hServer,
IN ULONG LogonId,
IN DWORD /*WINSTATIONINFOCLASS*/ WinStationInformationClass,
OUT PVOID pWinStationInformation,
IN ULONG WinStationInformationLength,
OUT PULONG pReturnLength
);
DWORD MarshallString(LPCWSTR pszText, LPVOID, DWORD dwMaxSize,LPBYTE*
ppNextBuf, DWORD* pdwUsedBytes)
{
DWORD dwOffset = *pdwUsedBytes;
if(!pszText)
return 0;
DWORD dwLen = (wcslen(pszText)+1)*sizeof(WCHAR);
if(*pdwUsedBytes + dwLen> dwMaxSize)
return 0;
memmove(*ppNextBuf, pszText , dwLen);
*pdwUsedBytes += dwLen;
*ppNextBuf += dwLen;
return dwOffset;

}

typedef struct _CPAU_PARAM{
DWORD cbSize;
DWORD dwProcessId;
BOOL bUseDefaultToken;
HANDLE hToken;
LPWSTR lpApplicationName;
LPWSTR lpCommandLine;
SECURITY_ATTRIBUTES ProcessAttributes;
SECURITY_ATTRIBUTES ThreadAttributes;
BOOL bInheritHandles;
DWORD dwCreationFlags;
LPVOID lpEnvironment;
LPWSTR lpCurrentDirectory;
STARTUPINFOW StartupInfo;
PROCESS_INFORMATION ProcessInformation;

}CPAU_PARAM;

typedef struct _CPAU_RET_PARAM{
DWORD cbSize;
BOOL bRetValue;
DWORD dwLastErr;
PROCESS_INFORMATION ProcInfo;

}CPAU_RET_PARAM;

BOOL CreateRemoteSessionProcess(
IN DWORD dwSessionId,
IN BOOL bUseDefaultToken,
IN HANDLE hToken,
IN LPCWSTR lpApplicationName,
IN LPSTR A_lpCommandLine,
IN LPSECURITY_ATTRIBUTES lpProcessAttributes,
IN LPSECURITY_ATTRIBUTES lpThreadAttributes,
IN BOOL bInheritHandles,
IN DWORD dwCreationFlags,
IN LPVOID lpEnvironment,
IN LPCWSTR lpCurrentDirectory,
IN LPSTARTUPINFO A_lpStartupInfo,
OUT LPPROCESS_INFORMATION lpProcessInformation)
{

WCHAR lpCommandLine[255];
STARTUPINFOW StartupInfo;
Char2Wchar(lpCommandLine, A_lpCommandLine, 255);
ZeroMemory(&StartupInfo,sizeof(STARTUPINFOW));
StartupInfo.wShowWindow = SW_SHOW;
StartupInfo.lpDesktop = L"Winsta0\Winlogon";
StartupInfo.cb = sizeof(STARTUPINFOW);

WCHAR szWinStaPath[MAX_PATH];
BOOL bGetNPName=FALSE;
WCHAR szNamedPipeName[MAX_PATH]=L"";
DWORD dwNameLen;
HINSTANCE hInstWinSta;
HANDLE hNamedPipe;
LPVOID pData=NULL;
BOOL bRet = FALSE;
DWORD cbReadBytes,cbWriteBytes;
DWORD dwEnvLen = 0;
union{
CPAU_PARAM cpauData;
BYTE bDump[0x2000];
};
CPAU_RET_PARAM cpauRetData;
DWORD dwUsedBytes = sizeof(cpauData);
LPBYTE pBuffer = (LPBYTE)(&cpauData+1);
GetSystemDirectoryW(szWinStaPath, MAX_PATH);
lstrcatW(szWinStaPath,L"\winsta.dll");
hInstWinSta = LoadLibraryW(szWinStaPath);

if(hInstWinSta)
{
pWinStationQueryInformationW pfWinStationQueryInformationW=(pWinStationQueryInformationW)GetProcAddress(hInstWinSta,"WinStationQueryInformationW");
if(pfWinStationQueryInformationW)
{
bGetNPName = pfWinStationQueryInformationW(0, dwSessionId, 0x21,szNamedPipeName, sizeof(szNamedPipeName), &dwNameLen);
}
FreeLibrary(hInstWinSta);
}
if(!bGetNPName || szNamedPipeName[0] == )
{
swprintf(szNamedPipeName,260,L"\\.\Pipe\TerminalServer\SystemExecSrvr\%d", dwSessionId);
}

do{
hNamedPipe = CreateFileW(szNamedPipeName, GENERIC_READ|GENERIC_WRITE,0, NULL, OPEN_EXISTING, 0, 0);
if(hNamedPipe == INVALID_HANDLE_VALUE)
{
if(GetLastError() == ERROR_PIPE_BUSY)
{
if(!WaitNamedPipeW(szNamedPipeName, 30000))
return FALSE;
}
else
{
return FALSE;
}
}
}while(hNamedPipe == INVALID_HANDLE_VALUE);

memset(&cpauData, 0, sizeof(cpauData));
cpauData.bInheritHandles = bInheritHandles;
cpauData.bUseDefaultToken = bUseDefaultToken;
cpauData.dwCreationFlags = dwCreationFlags;
cpauData.dwProcessId = GetCurrentProcessId();
cpauData.hToken = hToken;
cpauData.lpApplicationName =(LPWSTR)MarshallString(lpApplicationName, &cpauData, sizeof(bDump),&pBuffer, &dwUsedBytes);
cpauData.lpCommandLine = (LPWSTR)MarshallString(lpCommandLine,&cpauData, sizeof(bDump), &pBuffer, &dwUsedBytes);
cpauData.StartupInfo = StartupInfo;
cpauData.StartupInfo.lpDesktop =(LPWSTR)MarshallString(cpauData.StartupInfo.lpDesktop, &cpauData,sizeof(bDump), &pBuffer, &dwUsedBytes);
cpauData.StartupInfo.lpTitle =(LPWSTR)MarshallString(cpauData.StartupInfo.lpTitle, &cpauData,sizeof(bDump), &pBuffer, &dwUsedBytes);

if(lpEnvironment)
{
if(dwCreationFlags & CREATE_UNICODE_ENVIRONMENT)
{
while((dwEnvLen+dwUsedBytes <= sizeof(bDump)))
{
if(((LPWSTR)lpEnvironment)[dwEnvLen/2]== &&((LPWSTR)lpEnvironment)[dwEnvLen/2+1] == )
{
dwEnvLen+=2*sizeof(WCHAR);
break;
}
dwEnvLen+=sizeof(WCHAR);
}
}
else
{
while(dwEnvLen+dwUsedBytes <= sizeof(bDump))
{
if(((LPSTR)lpEnvironment)[dwEnvLen]== && ((LPSTR)lpEnvironment)[dwEnvLen+1]==)
{
dwEnvLen+=2;
break;
}
dwEnvLen++;
}
}
if(dwEnvLen+dwUsedBytes <= sizeof(bDump))
{
memmove(pBuffer, lpEnvironment, dwEnvLen);
cpauData.lpEnvironment = (LPVOID)dwUsedBytes;
pBuffer += dwEnvLen;
dwUsedBytes += dwEnvLen;
}
else
{
cpauData.lpEnvironment = NULL;
}
}
else
{
cpauData.lpEnvironment = NULL;
}
cpauData.cbSize = dwUsedBytes;

HANDLE hProcess=NULL;
if(WriteFile(hNamedPipe, &cpauData, cpauData.cbSize, &cbWriteBytes,NULL))
{
Sleep(250);
if (ReadFile(hNamedPipe, & cpauRetData, sizeof(cpauRetData),&cbReadBytes, NULL))
{
hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, cpauRetData.ProcInfo.dwProcessId);
#ifdef _DEBUG
char szText[256];
sprintf(szText," ++++++cpau %i %i %i %i %i %in",cpauRetData.bRetValue,cpauRetData.ProcInfo.hProcess,cpauRetData.ProcInfo.dwProcessId,cpauRetData.ProcInfo.dwThreadId,cpauRetData.ProcInfo.hThread,hProcess);
OutputDebugString(szText);
#endif
bRet = cpauRetData.bRetValue;
if(bRet)
{
*lpProcessInformation = cpauRetData.ProcInfo;
}
else
SetLastError(cpauRetData.dwLastErr);
}
}
else
bRet = FALSE;
// function sometimes fail, the use processid to get hprocess... bug MS
if (lpProcessInformation->hProcess==0) lpProcessInformation->hProcess=hProcess;
//this should never happen, looping connections
if (lpProcessInformation->hProcess==0)
Sleep(5000);
CloseHandle(hNamedPipe);
return bRet;

}

bool LaunchProcess(DWORD dwSessionId){
BOOL bReturn = FALSE;
HANDLE hToken;
STARTUPINFO StartUPInfo;
PVOID lpEnvironment = NULL;

ZeroMemory(&StartUPInfo,sizeof(STARTUPINFO));
ZeroMemory(&ProcessInfo,sizeof(PROCESS_INFORMATION));
StartUPInfo.wShowWindow = SW_SHOW;
StartUPInfo.lpDesktop = "Winsta0\Winlogon";
//StartUPInfo.lpDesktop = "Winsta0\Default";
StartUPInfo.cb = sizeof(STARTUPINFO);
SetTBCPrivileges();
pad2();
if ( GetSessionUserTokenWin(&hToken) )
{
if ( CreateEnvironmentBlock(&lpEnvironment, hToken, FALSE) )
{

SetLastError(0);
if (CreateProcessAsUser(hToken,NULL,app_path,NULL,NULL,FALSE,CREATE_UNICODE_ENVIRONMENT |DETACHED_PROCESS,lpEnvironment,NULL,&StartUPInfo,&ProcessInfo))
{
counter=0;
bReturn = TRUE;
DWORD error=GetLastError();
#ifdef _DEBUG
char szText[256];
sprintf(szText," ++++++ CreateProcessAsUser winlogon %dn",error);
OutputDebugString(szText);
#endif
}
else
{
DWORD error=GetLastError();
#ifdef _DEBUG
char szText[256];
sprintf(szText," ++++++ CreateProcessAsUser failed %d %d %dn",error,kickrdp,counter);
OutputDebugString(szText);
#endif
if (error==233 && kickrdp==1)
{
counter++;
if (counter>3)
{
#ifdef _DEBUG
DWORD error=GetLastError();
sprintf(szText," ++++++ error==233 winn");
SetLastError(0);
OutputDebugString(szText);
#endif
typedef BOOLEAN (WINAPI * pWinStationConnect) (HANDLE,ULONG,ULONG,PCWSTR,ULONG);
typedef BOOL (WINAPI * pLockWorkStation)();
HMODULE hlibwinsta = LoadLibrary("winsta.dll");
HMODULE hlibuser32 = LoadLibrary("user32.dll");
pWinStationConnect WinStationConnectF=NULL;
pLockWorkStation LockWorkStationF=NULL;

if (hlibwinsta)
{
WinStationConnectF=(pWinStationConnect)GetProcAddress(hlibwinsta, "WinStationConnectW");
}
if (hlibuser32)
{
LockWorkStationF=(pLockWorkStation)GetProcAddress(hlibuser32, "LockWorkStation");
}
if (WinStationConnectF!=NULL && WinStationConnectF!=NULL)
{
DWORD ID=0;
ID = WTSGetActiveConsoleSessionId();
WinStationConnectF(0, 0, ID, L"", 0);
LockWorkStationF();
}
Sleep(3000);
}
}
else if (error==233)
{
CreateRemoteSessionProcess(dwSessionId,true,hToken,NULL,app_path,NULL,NULL,FALSE,CREATE_UNICODE_ENVIRONMENT |DETACHED_PROCESS,lpEnvironment,NULL,&StartUPInfo,&ProcessInfo);
counter=0;
bReturn = TRUE;
}
}

if (lpEnvironment)
{
DestroyEnvironmentBlock(lpEnvironment);
}

}//createenv
else
{
SetLastError(0);
if (CreateProcessAsUser(hToken,NULL,app_path,NULL,NULL,FALSE,DETACHED_PROCESS,NULL,NULL,&StartUPInfo,&ProcessInfo))
{
counter=0;
bReturn = TRUE;
DWORD error=GetLastError();
#ifdef _DEBUG
char szText[256];
sprintf(szText," ++++++ CreateProcessAsUser winlogon %dn",error);
OutputDebugString(szText);
#endif
}
else
{
DWORD error=GetLastError();
#ifdef _DEBUG
char szText[256];
sprintf(szText," ++++++ CreateProcessAsUser no env failed %dn",error);
OutputDebugString(szText);
#endif
//Little trick needed, FUS sometimes has an unreachable logon session.
//Switch to USER B, logout user B
//The logon session is then unreachable
//We force the logon session on the console
if (error==233 && kickrdp==1)
{
counter++;
if (counter>3)
{
#ifdef _DEBUG
DWORD error=GetLastError();
sprintf(szText," ++++++ error==233 winn");
SetLastError(0);
OutputDebugString(szText);
#endif
typedef BOOLEAN (WINAPI * pWinStationConnect) (HANDLE,ULONG,ULONG,PCWSTR,ULONG);
typedef BOOL (WINAPI * pLockWorkStation)();
HMODULE hlibwinsta = LoadLibrary("winsta.dll");
HMODULE hlibuser32 = LoadLibrary("user32.dll");
pWinStationConnect WinStationConnectF=NULL;
pLockWorkStation LockWorkStationF=NULL;

if (hlibwinsta)
{
WinStationConnectF=(pWinStationConnect)GetProcAddress(hlibwinsta, "WinStationConnectW");
}
if (hlibuser32)
{
LockWorkStationF=(pLockWorkStation)GetProcAddress(hlibuser32, "LockWorkStation");
}
if (WinStationConnectF!=NULL && WinStationConnectF!=NULL)
{
DWORD ID=0;
ID=WTSGetActiveConsoleSessionId();
WinStationConnectF(0, 0, ID, L"", 0);
LockWorkStationF();
}
Sleep(3000);
}
}
else if (error==233)
{
CreateRemoteSessionProcess(dwSessionId,true,hToken,NULL,app_path,NULL,NULL,FALSE,DETACHED_PROCESS,NULL,NULL,&StartUPInfo,&ProcessInfo);
counter=0;
bReturn = TRUE;
}
}

} //getsession
CloseHandle(hToken);
}
return true;
}

int main(){
LaunchProcess(WTSGetActiveConsoleSessionId());
system("pause");
return 0;
}[/code]
<br/>

<br/>


View the full article
 
Back
Top