Solved

Problem getting CreateProcessWithLogonW to work!

Posted on 2003-11-05
20
1,539 Views
Last Modified: 2007-12-19
I am trying to use CreateProcessWithLogonW to execute an application that must be run as admin.  I am using this code:

 
    int bRes;               // results
      int creationflags;  // flags to pass to define window type
    int myerrorlevel;   // errorlevel for this function
    static PROCESS_INFORMATION myprocessinfo; // process return
    static STARTUPINFO mystartupinfo;
   
     // set window flags
      creationflags=CREATE_DEFAULT_ERROR_MODE | CREATE_NEW_CONSOLE | CREATE_NEW_PROCESS_GROUP;
   
     // initailise the startupinfo structure
     ::ZeroMemory(&mystartupinfo, sizeof(mystartupinfo));

     // load in size of structure
    mystartupinfo.cb = sizeof(mystartupinfo);

   bRes    =   CreateProcessWithLogonW(
                 L"administrator",
                 L"MACHINE",
                 L"PASSWORD",
                 LOGON_WITH_PROFILE ,
                 L"runas /profile /user:administrator notepad.exe",
                 NULL,
                 creationflags,
                 NULL,
                 0,
//                         NULL,
                        &mystartupinfo,
                        &myprocessinfo
               );

      CloseHandle (myprocessinfo.hThread);
      CloseHandle (myprocessinfo.hProcess);

      }
      
      if(enteredLoop != 1) {
            LPVOID lpMsgBuf;

            FormatMessage (
                                    FORMAT_MESSAGE_ALLOCATE_BUFFER |
                                    FORMAT_MESSAGE_FROM_SYSTEM |
                                    FORMAT_MESSAGE_IGNORE_INSERTS,
                                    NULL,
                                    GetLastError(),
                                    MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
                                    (LPTSTR) &lpMsgBuf,
                                    0,
                                    NULL
                                 );

            Console::Write("\nError: ");
            Console::Write((LPCTSTR)lpMsgBuf);
            Console::WriteLine("       Could not execute program as Administrator.\n");
      }



In parameter 10 if I use NULL everything compiles fun but the program crashes at runtime with:

Unhandled Exception: System.NullReferenceException: Object reference not set to
an instance of an object.
   at CreateProcessWithLogonW(UInt16* , UInt16* , UInt16* , UInt32 , UInt16* , U
Int16* , UInt32 , Void* , UInt16* , _STARTUPINFOW* , _PROCESS_INFORMATION* )
   at main(Int32 argc, SByte** argv) in c:\documents and settings\andre\my docum
ents\visual studio projects\mcc-trend-installer\mcc-trend-installer.cpp:line 148

If I try and use the  &mystartupinfo, I get this compile time error:

c:\Documents and Settings\andre\My Documents\Visual Studio Projects\MCC-Trend-Installer\MCC-Trend-Installer.cpp(148): error C2664: 'CreateProcessWithLogonW' : cannot convert parameter 10 from 'STARTUPINFO *' to 'LPSTARTUPINFOW'


This is VERY urgent and I need this app done and running TODAY thats why I am awarding 500 points.  Need some help ASAP to get this thing up and running.  Thanks.

0
Comment
Question by:acameron
  • 10
  • 6
  • 4
20 Comments
 
LVL 1

Accepted Solution

by:
LuCkY earned 500 total points
ID: 9686283
Have you tried using STARTUPINFOW instead of STARTUPINFO (or atleast make sure that you have defined UNICODE)? That explains why it can't convert the parameter, the structures look like this:

typedef struct _STARTUPINFOA {
    DWORD   cb;
    LPSTR   lpReserved;
    LPSTR   lpDesktop;
    LPSTR   lpTitle;
    DWORD   dwX;
    DWORD   dwY;
    DWORD   dwXSize;
    DWORD   dwYSize;
    DWORD   dwXCountChars;
    DWORD   dwYCountChars;
    DWORD   dwFillAttribute;
    DWORD   dwFlags;
    WORD    wShowWindow;
    WORD    cbReserved2;
    LPBYTE  lpReserved2;
    HANDLE  hStdInput;
    HANDLE  hStdOutput;
    HANDLE  hStdError;
} STARTUPINFOA, *LPSTARTUPINFOA;
typedef struct _STARTUPINFOW {
    DWORD   cb;
    LPWSTR  lpReserved;
    LPWSTR  lpDesktop;
    LPWSTR  lpTitle;
    DWORD   dwX;
    DWORD   dwY;
    DWORD   dwXSize;
    DWORD   dwYSize;
    DWORD   dwXCountChars;
    DWORD   dwYCountChars;
    DWORD   dwFillAttribute;
    DWORD   dwFlags;
    WORD    wShowWindow;
    WORD    cbReserved2;
    LPBYTE  lpReserved2;
    HANDLE  hStdInput;
    HANDLE  hStdOutput;
    HANDLE  hStdError;
} STARTUPINFOW, *LPSTARTUPINFOW;
#ifdef UNICODE
typedef STARTUPINFOW STARTUPINFO;
typedef LPSTARTUPINFOW LPSTARTUPINFO;
#else
typedef STARTUPINFOA STARTUPINFO;
typedef LPSTARTUPINFOA LPSTARTUPINFO;
#endif // UNICODE

As you can see it is important to use the wide version of the structure if you use the wide version of the function.
0
 

Author Comment

by:acameron
ID: 9686332
Still getting:

c:\Documents and Settings\andre\My Documents\Visual Studio Projects\MCC-Trend-Installer\MCC-Trend-Installer.cpp(196): error C2664: 'CreateProcessWithLogonW' : cannot convert parameter 10 from 'STARTUPINFOW *' to 'LPSTARTUPINFOW'
0
 
LVL 6

Expert Comment

by:GloomyFriar
ID: 9686341
(LPSTARTUPINFOW)&mystartupinfo
0
 

Author Comment

by:acameron
ID: 9686366
Strange:

c:\Documents and Settings\andre\My Documents\Visual Studio Projects\MCC-Trend-Installer\MCC-Trend-Installer.cpp(196): error C2664: 'CreateProcessWithLogonW' : cannot convert parameter 10 from 'LPSTARTUPINFOW' to 'LPSTARTUPINFOW'
0
 
LVL 6

Expert Comment

by:GloomyFriar
ID: 9686382
8-D
0
 

Author Comment

by:acameron
ID: 9686391
??? 8-D ????  What is that?  A Smiley face?
0
 
LVL 1

Expert Comment

by:LuCkY
ID: 9686395
I just copied and pasted the code you provided to a test application and it compiled without problem if you change:

static STARTUPINFO mystartupinfo;

to

static STARTUPINFOW mystartupinfo;

Take a look at how 'LPSTARTUPINFOW' is defined in WinBase.h. Maybe the file can provide you more information at what is going wrong... What version of the file are you using as it seems pretty weird to me that it can't convert 'STARTUPINFOW *' to 'LPSTARTUPINFOW' which is exactly the same :-)

You could also try declaring it as:

static LPSTARTUPINFOW mystartupinfo = new LPSTARTUPINFOW;

just to test if it works that way (you have to change all points to dereference pointers of course)
0
 
LVL 6

Expert Comment

by:GloomyFriar
ID: 9686416
try to
#define UNICODE
0
 

Author Comment

by:acameron
ID: 9686521
GRRRRR

c:\Documents and Settings\andre\My Documents\Visual Studio Projects\MCC-Trend-Installer\MCC-Trend-Installer.cpp(125): error C2228: left of '.cb' must have class/struct/union type

Why is this flagging up now?
0
 

Author Comment

by:acameron
ID: 9686532
Never mind, I now have:


      int bRes;               // results
      int creationflags;  // flags to pass to define window type
    static PROCESS_INFORMATION myprocessinfo; // process return
    static STARTUPINFO mystartupinfo;
   
     // set window flags
      creationflags=CREATE_DEFAULT_ERROR_MODE | CREATE_NEW_CONSOLE | CREATE_NEW_PROCESS_GROUP;
   
     // initailise the startupinfo structure
     ::ZeroMemory(&mystartupinfo, sizeof(mystartupinfo));

     // load in size of structure
      mystartupinfo.cb = sizeof(mystartupinfo);

      bRes    =   CreateProcessWithLogonW(
                                                       L"administrator",
                                                             L"andywks",
                                                     L"goober",
                                                     LOGON_WITH_PROFILE ,
                                                     L"runas /profile /user:administrator notepad.exe",
                                                     NULL,
                                                     creationflags,
                                                     NULL,
                                                     0,
                                                             (LPSTARTUPINFOW)&mystartupinfo,
                                                             &myprocessinfo
                                                          );

      CloseHandle (myprocessinfo.hThread);
      CloseHandle (myprocessinfo.hProcess);

      }
      
      if(enteredLoop != 1) {
            LPVOID lpMsgBuf;

            FormatMessage (
                                    FORMAT_MESSAGE_ALLOCATE_BUFFER |
                                    FORMAT_MESSAGE_FROM_SYSTEM |
                                    FORMAT_MESSAGE_IGNORE_INSERTS,
                                    NULL,
                                    GetLastError(),
                                    MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
                                    (LPTSTR) &lpMsgBuf,
                                    0,
                                    NULL
                                 );

            Console::Write("\nError: ");
            Console::Write((LPCTSTR)lpMsgBuf);
            Console::WriteLine("       Could not execute program as Administrator.\n");

which compiles but doesnt link, I get:

MCC-Trend-Installer fatal error LNK1561: entry point must be defined
0
How to run any project with ease

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

 
LVL 6

Expert Comment

by:GloomyFriar
ID: 9686541
Do you import the CreateProcessWithLogonW manually?
If so show me how it is declared.
My MSVC don't know about the function :(
0
 
LVL 1

Expert Comment

by:LuCkY
ID: 9686558
The above code is NOT correct (unless you have UNICODE defined :)). The STARTUPINFO structure is different from STARTUPINFOW and that code WILL fail at runtime. It might compile because you tell the compiler that you know better than it that the structure is LPSTARTUPINFOW instead of LPSTARTUPINFOA.

About the entry point, did you specify a custom entry point?

From MSDN:

entry point must be defined

The linker did not find an entry point. You may have intended to link as a DLL, in which case you should link with the /DLL option. You may have also forgotten to specify the name of the entry point; link with the /ENTRY option.

Otherwise, you should include a main, wmain, WinMain, or wMain function in your code.

The following sample generates LNK1561:

// LNK1561.cpp
// LNK1561 expected
int i;
// add a main function to resolve this error
0
 
LVL 1

Expert Comment

by:LuCkY
ID: 9686563
@GloomyFriar

You have to set Win2k and above as target, ie _WIN32_WINNT>=0x0500 and WINVER>=0x0500
0
 

Author Comment

by:acameron
ID: 9686588
I got it working, I had missed a dll.  Any who thanks for the help but I guess its back to the drawing bored because I get this error when I execute the application:

Error: The handle is invalid.
       Could not execute program as Administrator.

The first part after ERROR: of course comes from GetLastError().  What did I miss?
0
 

Author Comment

by:acameron
ID: 9686637
           enteredLoop = 1;

            CHString comStr( trendVersion );
            BSTR bComStr = comStr.AllocSysString();

            CHString sysName( machineName );
            BSTR bSysName = sysName.AllocSysString();

            CHString userName( L"administrator" );
            BSTR bUserName = userName.AllocSysString();

            CHString password( L"goober" );
            BSTR bPassword = password.AllocSysString();

//    int LOGON_WITH_PROFILE = 1;
//    int LOGON_NETCREDENTIALS_ONLY = 2;

      int bRes;               // results
      int creationflags;  // flags to pass to define window type
    static PROCESS_INFORMATION myprocessinfo; // process return
    static STARTUPINFO mystartupinfo;
   
     // set window flags
      creationflags=CREATE_DEFAULT_ERROR_MODE | CREATE_NEW_CONSOLE | CREATE_NEW_PROCESS_GROUP;
   
     // initailise the startupinfo structure
     ::ZeroMemory(&mystartupinfo, sizeof(mystartupinfo));

     // load in size of structure
      mystartupinfo.cb = sizeof(mystartupinfo);

      bRes    =   CreateProcessWithLogonW(
                                                       bComStr,
                                                             bSysName,
                                                     bPassword,
                                                     LOGON_WITH_PROFILE ,
                                                     bComStr,
                                                     NULL,
                                                     creationflags,
                                                     NULL,
                                                     0,
                                                             (LPSTARTUPINFOW)&mystartupinfo,
                                                             &myprocessinfo
                                                          );

      CloseHandle (myprocessinfo.hThread);
      CloseHandle (myprocessinfo.hProcess);

      if(!bRes){ enteredLoop = 0; }
0
 
LVL 1

Expert Comment

by:LuCkY
ID: 9686651
Do you know when the error flag is set? You'll have to be more specific if you want me to answer that :-) I mean that error could come from anywhere and I don't even know how that output is generated.
0
 

Author Comment

by:acameron
ID: 9686685
// This is the main project file for VC++ application project
// generated using an Application Wizard.

#include "stdafx.h"
#using <mscorlib.dll>
#include <WinSock.h>
#include <Windows.h>
#include <FwCommon.h>
#pragma comment(lib, "Framedyn.lib")
#pragma comment(lib, "wsock32.lib")
using namespace System;

// This is the entry point for this application
int _tmain(int argc, char *argv[])
{
      int installSoftware    = 0;
      int enteredLoop        = 0;
      HANDLE hAdminUserToken = 0;
      BOOL dwSpawnProc       = 0;
      char machineName[255];
      WORD wVersionRequested;
      WSADATA wsaData;
      wVersionRequested      = MAKEWORD( 1, 1 );
      char *trendVersion;
      
      if ( WSAStartup( wVersionRequested, &wsaData ) == 0 ) {
            gethostname(machineName, sizeof(machineName));
      }

      system("cls");
      Console::Write("***********************************\n");
      Console::Write("* Cybergnostic Trend AV Installer *\n");
      Console::Write("***********************************\n\n");

      Console::Write("1.) Trend For Win(95/98/ME)\n");
      Console::Write("2.) Trend For Win(NT/2000/XP)\n");
      Console::Write("3.) Quit\n\n");

      Console::Write("Selection ? ");
      int actionSelection = System::Convert::ToInt32(Console::ReadLine());

      switch(actionSelection) {
            case 1:
                  installSoftware  = 1;
                  trendVersion = "windows9598install.exe";
                  break;
            case 2:
                  installSoftware = 1;
                  trendVersion    = "windowsntinstall.exe";
                  break;
            default:
                  installSoftware = 0;
                  break;
      }

      if(installSoftware != 1) {
            exit(1);
      }

      if ( LogonUser( "administrator",
                      machineName,
                      "goober",
                      LOGON32_LOGON_BATCH,
                      LOGON32_PROVIDER_DEFAULT,
                      &hAdminUserToken )
            )
      {


          if ( ImpersonateLoggedOnUser (hAdminUserToken) )
          {
                  enteredLoop = 1;
                  system("C:\\Progra~1\\Intern~1\\IEXPLORE.EXE");
                  Console::Write("IN THE HOOD YALL");
          }

            RevertToSelf();
          hAdminUserToken = 0;
      }else {
            enteredLoop = 1;

            CHString comStr( trendVersion );
            BSTR bComStr = comStr.AllocSysString();

            CHString sysName( machineName );
            BSTR bSysName = sysName.AllocSysString();

            CHString userName( L"administrator" );
            BSTR bUserName = userName.AllocSysString();

            CHString password( L"goober" );
            BSTR bPassword = password.AllocSysString();

//    int LOGON_WITH_PROFILE = 1;
//    int LOGON_NETCREDENTIALS_ONLY = 2;

      int bRes; // results
      int creationflags;  // flags to pass to define window type
    static PROCESS_INFORMATION myprocessinfo; // process return
    static STARTUPINFOW mystartupinfo;
   
     // set window flags
      creationflags=CREATE_DEFAULT_ERROR_MODE | CREATE_NEW_CONSOLE | CREATE_NEW_PROCESS_GROUP;
   
     // initailise the startupinfo structure
     ::ZeroMemory(&mystartupinfo, sizeof(mystartupinfo));

     // load in size of structure
      mystartupinfo.cb = sizeof(mystartupinfo);

      bRes    =   CreateProcessWithLogonW(
                                                       bComStr,
                                                             bSysName,
                                                     bPassword,
                                                     LOGON_WITH_PROFILE ,
                                                     bComStr,
                                                     NULL,
                                                     creationflags,
                                                     NULL,
                                                     0,
                                                             (LPSTARTUPINFOW)&mystartupinfo,
                                                             &myprocessinfo
                                                          );

      CloseHandle (myprocessinfo.hThread);
      CloseHandle (myprocessinfo.hProcess);

      if(!bRes){ enteredLoop = 0; }

      }
      
      if(enteredLoop != 1) {
            LPVOID lpMsgBuf;

            FormatMessage (
                                    FORMAT_MESSAGE_ALLOCATE_BUFFER |
                                    FORMAT_MESSAGE_FROM_SYSTEM |
                                    FORMAT_MESSAGE_IGNORE_INSERTS,
                                    NULL,
                                    GetLastError(),
                                    MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
                                    (LPTSTR) &lpMsgBuf,
                                    0,
                                    NULL
                                 );

            Console::Write("\nError: ");
            Console::Write((LPCTSTR)lpMsgBuf);
            Console::WriteLine("       Could not execute program as Administrator.\n");
      }

    Console::Write("Hit Any Key to Continue ...");
      Console::ReadLine();
    return 0;
}
0
 
LVL 1

Expert Comment

by:LuCkY
ID: 9686747
What causes this problem, it can be at those parts, namely:

if ( ImpersonateLoggedOnUser (hAdminUserToken) )
         {
               enteredLoop = 1;
               system("C:\\Progra~1\\Intern~1\\IEXPLORE.EXE");
               Console::Write("IN THE HOOD YALL");
         }

If this fails enteredLoop never gets 1 or CreateProcessWithLogonW fails. Check which of the two is causing the failure, for instance by outputting some data here:

if ( ImpersonateLoggedOnUser (hAdminUserToken) )
         {
               enteredLoop = 1;
               system("C:\\Progra~1\\Intern~1\\IEXPLORE.EXE");
               Console::Write("IN THE HOOD YALL");
         }
else
        Console::Write("OHOH");
0
 

Author Comment

by:acameron
ID: 9686781
error was coming from:

//      CloseHandle (myprocessinfo.hThread);
//      CloseHandle (myprocessinfo.hProcess);

but by comenting them out I got a bad login error from the CreateProcessWithLogonW.  Checking this out now.  brb
0
 

Author Comment

by:acameron
ID: 9686819
You rock you win!  Problem was if you look at my CreateProcessWithLogonW.  Notice the first param is bComStr not bUserName :)  Everything works 100 % now! Thanks for ALL the help.
0

Featured Post

Find Ransomware Secrets With All-Source Analysis

Ransomware has become a major concern for organizations; its prevalence has grown due to past successes achieved by threat actors. While each ransomware variant is different, we’ve seen some common tactics and trends used among the authors of the malware.

Join & Write a Comment

Unlike C#, C++ doesn't have native support for sealing classes (so they cannot be sub-classed). At the cost of a virtual base class pointer it is possible to implement a pseudo sealing mechanism The trick is to virtually inherit from a base class…
Introduction This article is a continuation of the C/C++ Visual Studio Express debugger series. Part 1 provided a quick start guide in using the debugger. Part 2 focused on additional topics in breakpoints. As your assignments become a little more …
The viewer will learn how to clear a vector as well as how to detect empty vectors in C++.
The viewer will be introduced to the technique of using vectors in C++. The video will cover how to define a vector, store values in the vector and retrieve data from the values stored in the vector.

759 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

22 Experts available now in Live!

Get 1:1 Help Now