RunWithoutConsoleWindow.cpp
Go to the documentation of this file.
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set sw=2 :miv */
3 /*
4 //
5 // BEGIN SONGBIRD GPL
6 //
7 // This file is part of the Songbird web player.
8 //
9 // Copyright(c) 2005-2009 POTI, Inc.
10 // http://songbirdnest.com
11 //
12 // This file may be licensed under the terms of of the
13 // GNU General Public License Version 2 (the "GPL").
14 //
15 // Software distributed under the License is distributed
16 // on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either
17 // express or implied. See the GPL for the specific language
18 // governing rights and limitations.
19 //
20 // You should have received a copy of the GPL along with this
21 // program. If not, go to http://www.gnu.org/licenses/gpl.html
22 // or write to the Free Software Foundation, Inc.,
23 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
24 //
25 // END SONGBIRD GPL
26 //
27 */
28 
34 //------------------------------------------------------------------------------
35 //
36 // Run without console window imported services.
37 //
38 //------------------------------------------------------------------------------
39 
40 // Windows imports.
41 #include <fcntl.h>
42 #include <io.h>
43 #include <windows.h>
44 
45 // Std C imports.
46 #include <stdio.h>
47 
48 
49 //------------------------------------------------------------------------------
50 //
51 // Internal service prototypes.
52 //
53 //------------------------------------------------------------------------------
54 
55 static BOOL IsConsolePresent();
56 
57 static void InitStdio();
58 
59 
60 //------------------------------------------------------------------------------
61 //
62 // Public services.
63 //
64 //------------------------------------------------------------------------------
65 
90 int WINAPI wWinMain(HINSTANCE hInstance,
91  HINSTANCE hPrevInstance,
92  LPWSTR lpCmdLine,
93  int nCmdShow)
94 {
95  BOOL success;
96 
97  // Try attaching to parent's console.
98  AttachConsole(ATTACH_PARENT_PROCESS);
99 
100  // Check if a console is present.
101  BOOL isConsolePresent = IsConsolePresent();
102 
103  // Initialize stdio for debugging purposes.
104  InitStdio();
105 
106  // If no console is present, create the target process without a window.
107  DWORD creationFlags = 0;
108  if (!isConsolePresent)
109  creationFlags |= CREATE_NO_WINDOW;
110 
111  // Configure the target process to use our stdio handles.
112  STARTUPINFO startupInfo;
113  ZeroMemory(&startupInfo, sizeof(startupInfo));
114  startupInfo.cb = sizeof(startupInfo);
115  startupInfo.dwFlags = STARTF_USESTDHANDLES;
116  startupInfo.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
117  startupInfo.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE);
118  startupInfo.hStdError = GetStdHandle(STD_ERROR_HANDLE);
119 
120  // Create the target process.
121  PROCESS_INFORMATION processInfo;
122  success = CreateProcessW(NULL, // lpApplicationName.
123  lpCmdLine, // lpCommandLine.
124  NULL, // lpProcessAttributes.
125  NULL, // lpThreadAttributes.
126  TRUE, // bInheritHandles.
127  creationFlags, // dwCreationFlags.
128  NULL, // lpEnvironment.
129  NULL, // lpCurrentDirectory.
130  &startupInfo, // lpStartupInfo.
131  &processInfo); // lpProcessInformation.
132  if (!success) {
133  fprintf(stderr, "Internal error %d creating process.\n", GetLastError());
134  return -1;
135  }
136 
137  // Wait for the target process to complete.
138  WaitForSingleObject(processInfo.hProcess, INFINITE);
139 
140  // Get the target process exit code.
141  DWORD exitCode;
142  success = GetExitCodeProcess(processInfo.hProcess, &exitCode);
143  if (!success) {
144  fprintf(stderr, "Internal error %d getting exit code.\n", GetLastError());
145  return -1;
146  }
147 
148  return exitCode;
149 }
150 
151 
152 //------------------------------------------------------------------------------
153 //
154 // Internal services.
155 //
156 //------------------------------------------------------------------------------
157 
164 static BOOL IsConsolePresent()
165 {
166  // Try opening the console output. If this succeeds, a console is present.
167  HANDLE conoutHandle = CreateFileW(L"CONOUT$",
168  GENERIC_WRITE,
169  FILE_SHARE_WRITE,
170  NULL,
171  OPEN_EXISTING,
172  FILE_ATTRIBUTE_NORMAL,
173  NULL);
174  if (conoutHandle == INVALID_HANDLE_VALUE)
175  return FALSE;
176 
177  // Close the console output handle.
178  CloseHandle(conoutHandle);
179 
180  return TRUE;
181 }
182 
183 
188 static void InitStdio()
189 {
190  int osfHandle;
191  FILE* file;
192 
193  // Initialize stdin.
194  file = NULL;
195  osfHandle = _open_osfhandle
196  (reinterpret_cast<intptr_t>(GetStdHandle(STD_INPUT_HANDLE)),
197  _O_TEXT);
198  if (osfHandle != -1)
199  file = _fdopen(osfHandle, "r");
200  if (file)
201  *stdin = *file;
202 
203  // Initialize stdout.
204  file = NULL;
205  osfHandle = _open_osfhandle
206  (reinterpret_cast<intptr_t>(GetStdHandle(STD_OUTPUT_HANDLE)),
207  _O_TEXT);
208  if (osfHandle != -1)
209  file = _fdopen(osfHandle, "w");
210  if (file) {
211  *stdout = *file;
212  setvbuf(stdout, NULL, _IONBF, 0);
213  }
214 
215  // Initialize stderr.
216  file = NULL;
217  osfHandle = _open_osfhandle
218  (reinterpret_cast<intptr_t>(GetStdHandle(STD_ERROR_HANDLE)),
219  _O_TEXT);
220  if (osfHandle != -1)
221  file = _fdopen(osfHandle, "w");
222  if (file) {
223  *stderr = *file;
224  setvbuf(stderr, NULL, _IONBF, 0);
225  }
226 }
227 
static void InitStdio()
static BOOL IsConsolePresent()
int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int nCmdShow)
var file