/[rdesktop]/sourceforge.net/trunk/seamlessrdp/ServerExe/main.c
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Diff of /sourceforge.net/trunk/seamlessrdp/ServerExe/main.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1069 by ossman_, Thu Mar 9 09:46:30 2006 UTC revision 1093 by ossman_, Fri Mar 10 09:47:10 2006 UTC
# Line 1  Line 1 
1  //  /* -*- c-basic-offset: 8 -*-
2  // Copyright (C) 2004-2005 Martin Wickett     rdesktop: A Remote Desktop Protocol client.
3  //     Seamless windows - Remote server executable
4    
5       Based on code copyright (C) 2004-2005 Martin Wickett
6    
7       Copyright (C) Peter Åstrand <astrand@cendio.se> 2005-2006
8       Copyright (C) Pierre Ossman <ossman@cendio.se> 2006
9    
10       This program is free software; you can redistribute it and/or modify
11       it under the terms of the GNU General Public License as published by
12       the Free Software Foundation; either version 2 of the License, or
13       (at your option) any later version.
14    
15       This program is distributed in the hope that it will be useful,
16       but WITHOUT ANY WARRANTY; without even the implied warranty of
17       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18       GNU General Public License for more details.
19    
20       You should have received a copy of the GNU General Public License
21       along with this program; if not, write to the Free Software
22       Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23    */
24    
25  #include <windows.h>  #include <windows.h>
26  #include <stdio.h>  #include <stdio.h>
27    
28    #include "vchannel.h"
29    
30  #include "resource.h"  #include "resource.h"
31    
32  #define snprintf _snprintf  #define APP_NAME "SeamlessRDP Shell"
33    
34    /* Global data */
35    static HINSTANCE g_instance;
36    
37    typedef void (*set_hooks_proc_t) ();
38    typedef void (*remove_hooks_proc_t) ();
39    typedef int (*get_instance_count_proc_t) ();
40    
41  //  static void
42  // some global data  message(const char *text)
 //  
 HWND ghWnd;  
 NOTIFYICONDATA nid;  
 HINSTANCE hAppInstance;  
   
 #define WM_TRAY_NOTIFY ( WM_APP + 1000 )  
   
 static const char szAppName[] = "SeamlessRDP Shell";  
   
 typedef void ( *SetHooksProc ) ();  
 typedef void ( *RemoveHooksProc ) ();  
 typedef int ( *GetInstanceCountProc ) ();  
   
 //  
 // spawn a message box  
 //  
 void Message( const char *message )  
43  {  {
44      MessageBox( GetDesktopWindow(), message, "SeamlessRDP Shell", MB_OK );          MessageBox(GetDesktopWindow(), text, "SeamlessRDP Shell", MB_OK);
45  }  }
46    
47  //  static char *
48  // manage the tray icon  get_token(char **s)
 //  
 BOOL InitTrayIcon()  
49  {  {
50      nid.cbSize = sizeof( NOTIFYICONDATA );          char *comma, *head;
51      nid.hWnd = ghWnd;          head = *s;
52      nid.uID = 0;  
53      nid.uFlags = NIF_MESSAGE | NIF_ICON | NIF_TIP;          if (!head)
54      nid.uCallbackMessage = WM_TRAY_NOTIFY;                  return NULL;
55      strcpy( nid.szTip, szAppName );  
56      nid.hIcon = LoadIcon( hAppInstance, MAKEINTRESOURCE( IDI_TRAY ) );          comma = strchr(head, ',');
57            if (comma)
58      if ( Shell_NotifyIcon( NIM_ADD, &nid ) != TRUE ) {          {
59          Message( "Unable to create tray icon." );                  *comma = '\0';
60          return FALSE;                  *s = comma + 1;
61      }          }
62            else
63            {
64                    *s = NULL;
65            }
66    
67      return TRUE;          return head;
68  }  }
69    
70  //  static BOOL CALLBACK
71  // Remove tray icon  enum_cb(HWND hwnd, LPARAM lparam)
 //  
 BOOL RemoveTrayIcon()  
72  {  {
73      if ( Shell_NotifyIcon( NIM_DELETE, &nid ) != TRUE ) {          RECT rect;
74          Message( "Unable to remove tray icon." );          char title[150];
75          return FALSE;          LONG styles;
76      }          int state;
77    
78      return TRUE;          styles = GetWindowLong(hwnd, GWL_STYLE);
79    
80  }          if (!(styles & WS_VISIBLE))
81                    return TRUE;
82    
83  //          vchannel_write("CREATE,0x%p,0x%x", hwnd, 0);
 // manage the about dialog box  
 //  
 BOOL CALLBACK DialogProc( HWND hwndDlg, UINT uMsg, WPARAM wParam,  
                           LPARAM lParam )  
 {  
     if ( uMsg == WM_COMMAND ) {  
         WORD wID = LOWORD( wParam );  
         if ( wID == IDOK )  
             DestroyWindow( hwndDlg );  
     }  
84    
85      return 0;          if (!GetWindowRect(hwnd, &rect))
86  }          {
87                    debug("GetWindowRect failed!");
88                    return TRUE;
89            }
90    
91  void AboutDlg()          vchannel_write("POSITION,0x%p,%d,%d,%d,%d,0x%x",
92  {                         hwnd,
93      DialogBox( hAppInstance, MAKEINTRESOURCE( IDD_ABOUT ), NULL, DialogProc );                         rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, 0);
 }  
94    
95  //          GetWindowText(hwnd, title, sizeof(title));
96  // manage the context menu  
97  //          /* FIXME: Strip title of dangerous characters */
98  void DoContextMenu()  
99  {          if (styles & WS_MAXIMIZE)
100      HMENU hMenu, hSubMenu;                  state = 2;
101      POINT pt;          else if (styles & WS_MINIMIZE)
102          int cmd;                  state = 1;
103            else
104      hMenu = LoadMenu( hAppInstance, MAKEINTRESOURCE( IDR_TRAY ) );                  state = 0;
105      if ( hMenu == NULL ) {  
106          Message( "Unable to load menu ressource." );          vchannel_write("SETSTATE,0x%p,%s,0x%x,0x%x", hwnd, title, state, 0);
107          return ;  
108      }          return TRUE;
   
     hSubMenu = GetSubMenu( hMenu, 0 );  
     if ( hSubMenu == NULL ) {  
         Message( "Unable to find popup mennu." );  
         return ;  
     }  
   
     // get the cursor position  
     GetCursorPos( &pt );  
   
     SetForegroundWindow( ghWnd );  
     cmd = TrackPopupMenu( hSubMenu,  
                               TPM_RETURNCMD | TPM_LEFTALIGN | TPM_RIGHTBUTTON,  
                               pt.x, pt.y, 0, ghWnd, NULL );  
     DestroyMenu( hMenu );  
   
     switch ( cmd ) {  
     case ID_WMEXIT: {  
             PostQuitMessage( 0 );  
             break;  
         }  
     case ID_WMABOUT: {  
             AboutDlg();  
             break;  
         }  
     }  
109  }  }
110    
111  //  static void
112  // manage the main window  do_sync(void)
 //  
 LONG WINAPI MainWndProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam )  
113  {  {
114      switch ( uMsg ) {          vchannel_block();
     case WM_DESTROY: {  
             PostQuitMessage( 0 );  
             return 0;  
         }  
     case WM_TRAY_NOTIFY: {  
             if ( lParam == WM_RBUTTONDOWN )  
                 DoContextMenu();  
             return 0;  
         }  
     }  
115    
116      return DefWindowProc( hWnd, uMsg, wParam, lParam );          vchannel_write("SYNCBEGIN,0x0");
117    
118            EnumWindows(enum_cb, 0);
119    
120            vchannel_write("SYNCEND,0x0");
121    
122            vchannel_unblock();
123  }  }
124    
125  //  static void
126  //Init window  process_cmds(void)
 //  
 BOOL InitWindow()  
127  {  {
128      // register the frame class          char line[VCHANNEL_MAX_LINE];
129      WNDCLASS wndclass;          int size;
130      wndclass.style = 0;  
131      wndclass.lpfnWndProc = ( WNDPROC ) MainWndProc;          char *p, *tok1, *tok2, *tok3, *tok4, *tok5, *tok6, *tok7, *tok8;
     wndclass.cbClsExtra = 0;  
     wndclass.cbWndExtra = 0;  
     wndclass.hInstance = hAppInstance;  
     wndclass.hIcon = 0;  
     wndclass.hCursor = LoadCursor( NULL, IDC_ARROW );  
     wndclass.hbrBackground = ( HBRUSH ) ( COLOR_WINDOW + 1 );  
     wndclass.lpszMenuName = NULL;  
     wndclass.lpszClassName = szAppName;  
   
     if ( !RegisterClass( &wndclass ) ) {  
         Message( "Unable to register the window class." );  
         return FALSE;  
     }  
   
     // create the frame  
     ghWnd = CreateWindow( szAppName, szAppName,  
                           WS_OVERLAPPEDWINDOW | WS_CLIPSIBLINGS |  
                           WS_CLIPCHILDREN, CW_USEDEFAULT, CW_USEDEFAULT, 640,  
                           480, NULL, NULL, hAppInstance, NULL );  
   
     // make sure window was created  
     if ( !ghWnd ) {  
         Message( "Unable to create the window." );  
         return FALSE;  
     }  
132    
133      return TRUE;          while ((size = vchannel_read(line, sizeof(line))) >= 0)
134            {
135                    debug("Got: %s", line);
136    
137                    p = line;
138    
139                    tok1 = get_token(&p);
140                    tok2 = get_token(&p);
141                    tok3 = get_token(&p);
142                    tok4 = get_token(&p);
143                    tok5 = get_token(&p);
144                    tok6 = get_token(&p);
145                    tok7 = get_token(&p);
146                    tok8 = get_token(&p);
147    
148                    if (strcmp(tok1, "SYNC") == 0)
149                            do_sync();
150            }
151  }  }
152    
153  //  int WINAPI
154  // our main loop  WinMain(HINSTANCE instance, HINSTANCE prev_instance, LPSTR cmdline, int cmdshow)
 //  
 int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,  
                     LPSTR lpCmdLine, int nCmdShow )  
155  {  {
156      HMODULE hHookDLL;          HMODULE hookdll;
157      GetInstanceCountProc pfnInstanceCount;  
158      SetHooksProc pfnSetHooks;          set_hooks_proc_t set_hooks_fn;
159      RemoveHooksProc pfnRemoveHooks;          remove_hooks_proc_t remove_hooks_fn;
160            get_instance_count_proc_t instance_count_fn;
161      hAppInstance = hInstance;  
162            g_instance = instance;
163      hHookDLL = LoadLibrary( "hookdll.dll" );  
164      if ( !hHookDLL ) {          hookdll = LoadLibrary("seamlessrdp.dll");
165          Message( "Could not load hook DLL. Unable to continue." );          if (!hookdll)
166          return -1;          {
167      }                  message("Could not load hook DLL. Unable to continue.");
168                    return -1;
169      pfnInstanceCount = (GetInstanceCountProc) GetProcAddress( hHookDLL, "GetInstanceCount" );          }
170      pfnSetHooks = (SetHooksProc) GetProcAddress( hHookDLL, "SetHooks" );  
171      pfnRemoveHooks = (RemoveHooksProc) GetProcAddress( hHookDLL, "RemoveHooks" );          set_hooks_fn = (set_hooks_proc_t) GetProcAddress(hookdll, "SetHooks");
172            remove_hooks_fn = (remove_hooks_proc_t) GetProcAddress(hookdll, "RemoveHooks");
173      if ( !pfnInstanceCount || !pfnSetHooks || !pfnRemoveHooks ) {          instance_count_fn = (get_instance_count_proc_t) GetProcAddress(hookdll, "GetInstanceCount");
174          FreeLibrary( hHookDLL );  
175          Message( "Hook DLL doesn't contain the correct functions. Unable to continue." );          if (!set_hooks_fn || !remove_hooks_fn || !instance_count_fn)
176          return -1;          {
177      }                  FreeLibrary(hookdll);
178                    message("Hook DLL doesn't contain the correct functions. Unable to continue.");
179      /* Check if the DLL is already loaded */                  return -1;
180      if ( pfnInstanceCount() != 1 ) {          }
181          FreeLibrary( hHookDLL );  
182          Message( "Another running instance of Seamless RDP detected." );          /* Check if the DLL is already loaded */
183          return -1;          if (instance_count_fn() != 1)
184      }          {
185                    FreeLibrary(hookdll);
186      pfnSetHooks();                  message("Another running instance of Seamless RDP detected.");
187                    return -1;
188      // if we have been specified an app to launch, we will wait until the app has closed and use that for          }
189      // our cue to exit  
190      if ( strlen( lpCmdLine ) > 0 ) {          vchannel_open();
191          // Because we do not have a explorer.exe we need to make this application the replacement  
192          // shell. We do this by calling SystemParametersInfo. If we don't do this, we won't get the WH_SHELL notifications.          set_hooks_fn();
193    
194          MINIMIZEDMETRICS mmm;          /* Since we don't see the entire desktop we must resize windows
195          PROCESS_INFORMATION procInfo;             immediatly. */
196          STARTUPINFO startupInfo = {          SystemParametersInfo(SPI_SETDRAGFULLWINDOWS, TRUE, NULL, 0);
197                                        0  
198                                    };          /* Disable screen saver since we cannot catch its windows. */
199          char attr[] = "";          SystemParametersInfo(SPI_SETSCREENSAVEACTIVE, FALSE, NULL, 0);
200          LPTSTR process = lpCmdLine;  
201          DWORD dwExitCode;          if (strlen(cmdline) == 0)
202          BOOL m_create;          {
203                    message("No command line specified.");
204          // From MSDN:                  return -1;
205          // Note that custom shell applications do not receive WH_SHELL messages. Therefore, any application that          }
206          // registers itself as the default shell must call the SystemParametersInfo function with SPI_SETMINIMIZEDMETRICS          else
207          // before it (or any other application) can receive WH_SHELL messages.          {
208                    BOOL result;
209          mmm.cbSize = sizeof( MINIMIZEDMETRICS );                  DWORD exitcode;
210          SystemParametersInfo( SPI_SETMINIMIZEDMETRICS,                  PROCESS_INFORMATION proc_info;
211                                sizeof( MINIMIZEDMETRICS ), &mmm, 0 );                  STARTUPINFO startup_info;
212    
213          // We require DragFullWindows                  memset(&startup_info, 0, sizeof(STARTUPINFO));
214          SystemParametersInfo( SPI_SETDRAGFULLWINDOWS, TRUE, NULL, 0 );                  startup_info.cb = sizeof(STARTUPINFO);
215    
216          //set the current directory to that of the requested app .exe location                  result = CreateProcess(NULL, cmdline, NULL, NULL, FALSE, 0,
217          //tokenise lpCmdLine. first is the exe path. second (if exists) is the current directory to set.                                         NULL, NULL, &startup_info, &proc_info);
218          //SetCurrentDirectory ();  
219                    if (result)
220          //start process specified from command line arg.                  {
221          startupInfo.cb = sizeof( STARTUPINFO );                          do
222                            {
223          m_create =                                  process_cmds();
224              CreateProcess( NULL, process, NULL, NULL, FALSE, 0, NULL, NULL,                                  Sleep(100);
225                             &startupInfo, &procInfo );                                  GetExitCodeProcess(proc_info.hProcess, &exitcode);
226                            }
227          if ( m_create != FALSE ) {                          while (exitcode == STILL_ACTIVE);
228              // A loop to watch the process.  
229              GetExitCodeProcess( procInfo.hProcess, &dwExitCode );                          // Release handles
230                            CloseHandle(proc_info.hProcess);
231              while ( dwExitCode == STILL_ACTIVE ) {                          CloseHandle(proc_info.hThread);
232                  GetExitCodeProcess( procInfo.hProcess, &dwExitCode );                  }
233                  Sleep( 1000 );                  else
234              }                  {
235                            // CreateProcess failed.
236              // Release handles                          char msg[256];
237              CloseHandle( procInfo.hProcess );                          _snprintf(msg, sizeof(msg),
238              CloseHandle( procInfo.hThread );                                    "Unable to launch the requested application:\n%s", cmdline);
239          } else {                          message(msg);
240              // CreateProcess failed.                  }
241              char msg[ 256 ];          }
             snprintf( msg, sizeof( msg ), "Unable to launch the requested application:\n%s", process );  
             Message( msg );  
         }  
     } else  
         // we are launching without an app, therefore we will show the system tray app and wait for the user to close it  
     {  
         MSG msg;  
   
                 // create a dummy window to receive WM_QUIT message  
         InitWindow();  
   
         // create the tray icon  
         InitTrayIcon();  
   
         // just get and dispatch messages until we're killed  
         while ( GetMessage( &msg, 0, 0, 0 ) ) {  
             TranslateMessage( &msg );  
             DispatchMessage( &msg );  
         };  
   
         // remove our tray icon  
         RemoveTrayIcon();  
     }  
242    
243            remove_hooks_fn();
244    
245      // remove hook before saying goodbye          FreeLibrary(hookdll);
     pfnRemoveHooks();  
246    
247      FreeLibrary( hHookDLL );          vchannel_close();
248    
249      return 1;          return 1;
250  }  }

Legend:
Removed from v.1069  
changed lines
  Added in v.1093

  ViewVC Help
Powered by ViewVC 1.1.26