1  /* MsgBox.c v1.0 - 2011-05-07
  2  Update: http://myc01.free.fr/msgbox
  3  
  4  License: Public Domain Dedication (CC0 1.0)
  5    http://creativecommons.org/publicdomain/zero/1.0/
  6  */
  7  
  8  #include <stdio.h>
  9  #include <stdlib.h>
 10  #include <string.h>
 11  #include <windows.h>
 12  
 13  #define MAX_LIB                 32
 14  
 15  #define PROG_NAME               "MsgBox"
 16  #define PROG_VERSION            "1.0"
 17  #define PROG_DATE               "2011-05-07"
 18  #define PROG_LICENSE            "Public Domain Dedication (CC0 1.0)"
 19  
 20  #define Call(func)              if(func)func
 21  #define rCall(func)             (!func)?0:func
 22  #define InitLibs(size)          calloc (size, sizeof (LIB))
 23  #define Declare(rtype,nfunc)    typedef rtype (__stdcall * (nfunc))
 24  
 25  /*
 26  typedef  int (__stdcall * (impMessageBoxA)) (HANDLE hWnd, LPCSTR lpText, LPCSTR lpCaption, UINT uType); */
 27  Declare (int,              impMessageBoxA ) (HANDLE hWnd, LPCSTR lpText, LPCSTR lpCaption, UINT uType);
 28  
 29  typedef struct tagLIB
 30  {
 31      HANDLE hLib;
 32      PCHAR  nameLib;
 33  } LIB, *PLIB, *LPLIB;
 34  
 35  
 36  PVOID ImportLib (HANDLE *hLib, LPCSTR strLib, LPCSTR func)
 37  {
 38      if (!strLib || !func)
 39          return NULL;
 40  
 41      if (!*hLib)  // Load DLL file
 42          if (! (*hLib = LoadLibraryA (strLib)))
 43              return NULL;
 44  
 45      return GetProcAddress (*hLib, func);  // Get function pointer
 46  }  // ImportLib
 47  
 48  
 49  PCHAR SetStr (PCHAR *str_out, LPCSTR str_in)
 50  {
 51      if (*str_out)
 52          free (*str_out);
 53      *str_out = NULL;
 54  
 55      if (!str_in)
 56          return (*str_out = NULL);
 57  
 58      *str_out = malloc (strlen (str_in) + 1);
 59      return strcpy (*str_out, str_in);
 60  }  // SetStr
 61  
 62  
 63  PVOID ImportLibs (LIB *listLib, int size, LPCSTR strLib, LPCSTR func)
 64  {
 65      int i, h0 = -1;
 66  
 67      if (!strLib || !func)
 68          return NULL;
 69  
 70      for (i = 0; i < size; i++)
 71          if (listLib[i].hLib && listLib[i].nameLib)
 72          {
 73              if (!strcmp (listLib[i].nameLib, strLib))
 74                  break;
 75          }
 76          else if (h0 == -1) h0 = i;
 77  
 78      if ( (h0 != -1) && (i == size))
 79      {
 80          i = h0;
 81          listLib[i].hLib = LoadLibraryA (strLib);
 82          SetStr (&listLib[i].nameLib, strLib);
 83      }
 84      if (i < size)
 85          return GetProcAddress (listLib[i].hLib, func);
 86  
 87      return NULL;
 88  }  // ImportLibs
 89  
 90  
 91  void FreeLibs (LIB *listLib, int size)
 92  {
 93      int i;
 94      for (i = 0; i < size; i++)
 95          if (listLib[i].hLib || listLib[i].nameLib)
 96          {
 97              if (listLib[i].hLib)
 98                  FreeLibrary (listLib[i].hLib);
 99              if (listLib[i].nameLib)
100                  free (listLib[i].nameLib);
101              listLib[i].hLib = listLib[i].nameLib = NULL;
102          }
103      free (listLib);
104  }  // FreeLibs
105  
106  
107  char *replace (char *orgstr, const char *oldstr, const char *newstr)
108  {
109      int oldlen, newlen;
110      char *p, *s = orgstr;
111      while (s)
112      {
113          if (! (p = strstr (s, oldstr)))
114              return orgstr;
115          oldlen = strlen (oldstr);
116          newlen = strlen (newstr);
117          orgstr = (char*) realloc (orgstr, strlen (orgstr) - oldlen + newlen + 1);
118          if (!orgstr)
119              return NULL;
120          memmove (p + newlen, p + oldlen, strlen (p + oldlen) + 1);
121          memcpy (p, newstr, newlen);
122          s = p + newlen;
123      }
124      return orgstr;
125  }  // replace
126  
127  
128  int main (int argc, char *argv[])
129  {
130      char *help = PROG_NAME" v"PROG_VERSION" - ("PROG_DATE")  "  // [27] : ") \n"
131                   "License: "PROG_LICENSE"\n\n"
132                   "Usage: MsgBox.exe \"Message text...\" [buttons]\n"
133                   "With buttons:\n"
134                   "   0 = OK\n"
135                   "   1 = OK and Cancel\n"
136                   "   2 = Abort, Retry, and Ignore\n"
137                   "   3 = Yes, No, and Cancel\n"
138                   "   4 = Yes and No\n"
139                   "   5 = Retry and Cancel\n"
140                   "   6 = Cancel, Try Again, Continue\n\n"
141                   "Return values in \"%ErrorLevel%\" :\n"
142                   "   1 = OK\n"
143                   "   2 = Cancel\n"
144                   "   3 = Abort\n"
145                   "   4 = Retry\n"
146                   "   5 = Ignore\n"
147                   "   6 = Yes\n"
148                   "   7 = No\n"
149                   "  10 = Try Again\n"
150                   "  11 = Continue";
151  
152      if (argc == 1)
153      {
154          puts (help);
155          help[27] = '\n';
156          HANDLE hLibUser32 = NULL;
157          impMessageBoxA MsgBox1 = (impMessageBoxA) ImportLib (&hLibUser32, "user32.dll", "MessageBoxA");
158          Call (MsgBox1) (NULL, help, "Help", MB_ICONINFORMATION);  // Call without result
159          FreeLibrary (hLibUser32);  // Unload DLL file
160          return 0;
161      }
162  
163      int len, buttons = (argc >= 3) ? atoi (argv[2]) : 0;
164      if (argc >= 2)
165      {
166          help = argv[1];
167          replace (help, "//b", "\b");
168          replace (help, "//n", "\n");
169          replace (help, "//t", "\t");
170          replace (help, "%"  , "%%");
171      }
172  
173      len = strlen (help);
174      char *lpBuf = malloc (len + 1);
175      len = _snprintf (lpBuf, len, help);
176      lpBuf[len] = '\0';
177      free (help);
178  
179      PLIB Libs = InitLibs (MAX_LIB);
180      impMessageBoxA MsgBox2 = (impMessageBoxA) ImportLibs (Libs, MAX_LIB, "user32.dll", "MessageBoxA");
181      int result = rCall (MsgBox2) (NULL, lpBuf, "Message", buttons);  // Call with result
182      FreeLibs (Libs, MAX_LIB);
183      free (lpBuf);
184  
185      printf ("result=%d", result);
186      return result;
187  }  // main