winExec.cpp 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194
  1. //-----------------------------------------------------------------------------
  2. // Copyright (c) 2012 GarageGames, LLC
  3. //
  4. // Permission is hereby granted, free of charge, to any person obtaining a copy
  5. // of this software and associated documentation files (the "Software"), to
  6. // deal in the Software without restriction, including without limitation the
  7. // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  8. // sell copies of the Software, and to permit persons to whom the Software is
  9. // furnished to do so, subject to the following conditions:
  10. //
  11. // The above copyright notice and this permission notice shall be included in
  12. // all copies or substantial portions of the Software.
  13. //
  14. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  19. // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  20. // IN THE SOFTWARE.
  21. //-----------------------------------------------------------------------------
  22. #include "platformWin32/platformWin32.h"
  23. #include "console/console.h"
  24. #include "console/engineAPI.h"
  25. #include "console/simBase.h"
  26. #include "core/strings/unicode.h"
  27. #include "platform/threads/thread.h"
  28. #include "platform/threads/mutex.h"
  29. #include "core/util/safeDelete.h"
  30. #include "util/tempAlloc.h"
  31. //-----------------------------------------------------------------------------
  32. // Thread for executing in
  33. //-----------------------------------------------------------------------------
  34. class ExecuteThread : public Thread
  35. {
  36. // [tom, 12/14/2006] mProcess is only used in the constructor before the thread
  37. // is started and in the thread itself so we should be OK without a mutex.
  38. HANDLE mProcess;
  39. public:
  40. ExecuteThread(const char *executable, const char *args = NULL, const char *directory = NULL);
  41. virtual void run(void *arg = 0);
  42. };
  43. //-----------------------------------------------------------------------------
  44. // Event for cleanup
  45. //-----------------------------------------------------------------------------
  46. class ExecuteCleanupEvent : public SimEvent
  47. {
  48. ExecuteThread *mThread;
  49. bool mOK;
  50. public:
  51. ExecuteCleanupEvent(ExecuteThread *thread, bool ok)
  52. {
  53. mThread = thread;
  54. mOK = ok;
  55. }
  56. virtual void process(SimObject *object)
  57. {
  58. if( Con::isFunction( "onExecuteDone" ) )
  59. Con::executef( "onExecuteDone", Con::getIntArg( mOK ) );
  60. SAFE_DELETE(mThread);
  61. }
  62. };
  63. //-----------------------------------------------------------------------------
  64. ExecuteThread::ExecuteThread(const char *executable, const char *args /* = NULL */, const char *directory /* = NULL */) : Thread(0, NULL, false)
  65. {
  66. SHELLEXECUTEINFO shl;
  67. dMemset(&shl, 0, sizeof(shl));
  68. shl.cbSize = sizeof(shl);
  69. shl.fMask = SEE_MASK_NOCLOSEPROCESS;
  70. char exeBuf[1024];
  71. Platform::makeFullPathName(executable, exeBuf, sizeof(exeBuf));
  72. TempAlloc< TCHAR > dirBuf( ( directory ? dStrlen( directory ) : 0 ) + 1 );
  73. dirBuf[ dirBuf.size - 1 ] = 0;
  74. #ifdef UNICODE
  75. WCHAR exe[ 1024 ];
  76. convertUTF8toUTF16( exeBuf, exe );
  77. TempAlloc< WCHAR > argsBuf( ( args ? dStrlen( args ) : 0 ) + 1 );
  78. argsBuf[ argsBuf.size - 1 ] = 0;
  79. if( args )
  80. convertUTF8toUTF16N( args, argsBuf, argsBuf.size );
  81. if( directory )
  82. convertUTF8toUTF16N( directory, dirBuf, dirBuf.size );
  83. #else
  84. char* exe = exeBuf;
  85. char* argsBuf = args;
  86. if( directory )
  87. dStrpcy( dirBuf, directory );
  88. #endif
  89. backslash( exe );
  90. backslash( dirBuf );
  91. shl.lpVerb = TEXT( "open" );
  92. shl.lpFile = exe;
  93. shl.lpParameters = argsBuf;
  94. shl.lpDirectory = dirBuf;
  95. shl.nShow = SW_SHOWNORMAL;
  96. if(ShellExecuteEx(&shl) && shl.hProcess)
  97. {
  98. mProcess = shl.hProcess;
  99. start();
  100. }
  101. }
  102. void ExecuteThread::run(void *arg /* = 0 */)
  103. {
  104. if(mProcess == NULL)
  105. return;
  106. DWORD wait = WAIT_OBJECT_0 - 1; // i.e., not WAIT_OBJECT_0
  107. while(! checkForStop() && (wait = WaitForSingleObject(mProcess, 200)) != WAIT_OBJECT_0) ;
  108. Sim::postEvent(Sim::getRootGroup(), new ExecuteCleanupEvent(this, wait == WAIT_OBJECT_0), -1);
  109. }
  110. //-----------------------------------------------------------------------------
  111. // Console Functions
  112. //-----------------------------------------------------------------------------
  113. DefineEngineFunction( shellExecute, bool, (const char * executable, const char * args, const char * directory), ("", ""), "(string executable, string args, string directory)"
  114. "@brief Launches an outside executable or batch file\n\n"
  115. "@param executable Name of the executable or batch file\n"
  116. "@param args Optional list of arguments, in string format, to pass to the executable\n"
  117. "@param directory Optional string containing path to output or shell\n"
  118. "@return true if executed, false if not\n"
  119. "@ingroup Platform")
  120. {
  121. ExecuteThread *et = new ExecuteThread( executable, args, directory );
  122. if(! et->isAlive())
  123. {
  124. delete et;
  125. return false;
  126. }
  127. return true;
  128. }
  129. #ifndef TORQUE_SDL
  130. void Platform::openFolder(const char* path )
  131. {
  132. char filePath[1024];
  133. Platform::makeFullPathName(path, filePath, sizeof(filePath));
  134. #ifdef UNICODE
  135. WCHAR p[ 1024 ];
  136. convertUTF8toUTF16( filePath, p );
  137. #else
  138. char* p = filePath;
  139. #endif
  140. backslash( p );
  141. ::ShellExecute( NULL,TEXT("explore"),p, NULL, NULL, SW_SHOWNORMAL);
  142. }
  143. void Platform::openFile(const char* path )
  144. {
  145. char filePath[1024];
  146. Platform::makeFullPathName(path, filePath, sizeof(filePath));
  147. #ifdef UNICODE
  148. WCHAR p[ 1024 ];
  149. convertUTF8toUTF16( filePath, p );
  150. #else
  151. char* p = filePath;
  152. #endif
  153. backslash( p );
  154. ::ShellExecute( NULL,TEXT("open"),p, NULL, NULL, SW_SHOWNORMAL);
  155. }
  156. #endif // !TORQUE_SDL