tags:

views:

115

answers:

5

Hi!

I made an application and a dll, which are working this way: I have to register the dll. After registering the dll if i right click on an .exe file, the pop-up menu appears, and i have inserted into this menu one line ("Start MyApp"), and if i click there, it should start MyApp. MyApp has one parameter which is the full path of the selected .exe file. After starting MyApp with this path it should create a process with CreateProcessWithLogonW(). This application reads the username, password and the domain from an .ini file. My problem is, that after MyApp starts, it fails always, because it can't find the ini file. Errorcode is: 1 (Incorrect function). If i start MyApp manually, than it works fine.

Does anyone has any idea why is this, and how could i fix this problem?

Thanks in advance!

kampi

Update1:

Here is the code which reads from the ini file.

int main ( int argc, char *argv[] )  
{    
  int i, slash = 0, j;  
  char application[size];  
  wchar_t wuser[65], wdomain[33], wpass[129];  

  memset( user, 0, sizeof ( user ) );
  memset( password, 0, sizeof ( password ) );
  memset( domain, 0, sizeof ( domain ) );

  file_exists( "RunAs.ini" );
  readfile( "RunAs.ini" );  
  ....
  ....
  ....
}  
void file_exists( const char * filename )  
{  
  if (FILE * file = fopen(filename, "r"))  
  {  
      fclose(file);  
  }  
  else   
  {  
      printf("\nCan't find %s!\n",filename);  
      getch();  
      exit(1);  
  }   
}//file_exists    

void readfile( char * filename )
{  
     FILE *inifile;  
    char tmp[256], buf[256], what[128];  
    int i, j;  

    inifile = fopen( "RunAs.ini", "r" );  

    while ( fgets(tmp, sizeof tmp, inifile) != NULL )  
    {     
        if ( tmp[ strlen(tmp) - 1 ] == '\n' )  
         {  
            tmp[ strlen(tmp) - 1 ] = '\0';  
        }//if  

        memset ( buf, 0, sizeof( buf ) );  

        for ( i = 0; tmp[i]!= '='; i++ )  
         {  
             buf[i] = tmp[i];  
         }  
        buf[i] = '\0';  
        i++;  

    //  memset ( what, 0, sizeof( what ) );  
        SecureZeroMemory( what, sizeof(what) * 128 );  

        for ( j = 0; i != strlen(tmp); i++ )   
         {  
             what[j] = tmp[i];  
            j++;  
         }  
        what[j] = '\0';  
        upcase( buf );  
        removespace( what );  

        if ( strcmp( buf, "USERNAME" ) == 0 )  
        {  
            strcpy( user, what );  
        }  
        if ( strcmp( buf, "PASSWORD" ) == 0 )  
        {  
            strcpy( password, what );  
        }  
        if ( strcmp( buf, "DOMAIN" ) == 0 )  
        {  
            strcpy( domain, what );  
        }  
    }//while  
    fclose (inifile);  

}//readfile  
A: 

Are you providing an absolute path or a relative path? Your CWD may be different on startup.

Noctis Skytower
A: 

When starting your application directly, the current path is the path that your application is installed to.

However, when starting it from that context menu, the current path is something else.

There are two ways to resolve this. First, don't use an ini file. Instead, store your information to the registry. That way you don't care where the program is started from.

Alternatively, your app will have to locate the directory where it was actually installed, then load the ini file from there.

Obviously the first choice is the easiest path.

Chris Lively
A: 

Have you checked whether file path for the ini is valid ?

Ashish
@Mac:Yes, i have checked, and i tried give it an absolute and realtive path too.
kampi
+1  A: 

I suspect you're looking for the ini file in the wrong folder. I would try changing the ini file name in the application to the fully qualified name of the ini file. (i.e from "foo.ini" to "c:\\temp\\foo.ini")

(Please note that I've doubled the backslashes because without this, the single backslash may change the meaning of the next character or the backslash may be ignored.)

David Harris
@David:I tried both way, "Runas.ini", and "d:\kampi\runas.ini" too, but neither worked. But if i start this exe manually, then it works fine, and i don't have any idea why is this.
kampi
@Kampi: have you tried "d:\\kampi\\runas.ini" or if you are in c# (i do not know if it works in c++) @"d:\kampi\runas.ini"
Scott Chamberlain
@kampi: Please note my last sentence -- where it specifies that you must double the the backslashes. The file name should read "d:\\kampi\\runas.ini". Otherwise the first \ character may be ignored and the second one and the r replaced by a carriage return (0x0d) (I've editied my original post to make this more clear.)
David Harris
@Dave:I wrote double backslashes in the code, i forgot only here to double them
kampi
+3  A: 

As others have said, your problem is here:

file_exists( "RunAs.ini" );
readfile( "RunAs.ini" );  

Neither of the function calls provides a path. You're expecting the current working directory to be the folder where your application is located, but it doesn't have to be (in fact, you should never assume that it is). The context menu isn't setting the working directory first.

Your safest bet is to retrieve the path to your folder using the path provided in argv[] (the 0th element is the fully qualified path and name of the application itself, and you can extract the path from that). You'll then have exact knowledge of where the file is located, and can append the name of the ini file to that path.

Ken White
@Ken:You're right! That was the mistake.I needed the pull path, not only the filename. However it was in the same directory. I don't understand fully, why is that, because untill this i used only the above form, and it always worked perfectly. Thank you very mutch!
kampi
There is no guarantee that the first argv element is a fully qualified path to anything at all. Since we know this is only for Windows, call GetModuleFileName as Microsoft recommends: http://msdn.microsoft.com/en-us/library/88w63h9k.aspx
Rob Kennedy
@Rob: Well, which compiler on +Windows+ doesn't return the full path to the app in the first argv element (for future reference). I also presumed that, since the OP wasn't using WritePrivateProfileString or any other API functionality, there was a reason not to recommend GetModuleFileName.
Ken White