Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

214 lines
6.0 KiB

  1. /*
  2. * exe.c Get info from a EXEHDR
  3. *
  4. * Modification History:
  5. *
  6. * 4/03/89 ToddLa Wrote it
  7. * 4/09/90 T-JackD modification such that the type of error is reflected...
  8. * 4/17/90 t-jackd modification such that notification of error can be set...
  9. * 4/20/2001 BryanSt improved the error checking to bring the code into the 21st centry.
  10. */
  11. #include "priv.h"
  12. #pragma hdrstop
  13. #include <newexe.h>
  14. #include "exe.h"
  15. static DWORD dwDummy;
  16. #define FOPEN(sz) CreateFile(sz, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL )
  17. #define FCLOSE(fh) CloseHandle(fh)
  18. #define FREAD(fh,buf,len) (ReadFile(fh,buf,len, &dwDummy, NULL) ? dwDummy : HFILE_ERROR)
  19. #define FSEEK(fh,off,i) SetFilePointer(fh,(DWORD)off, NULL, i)
  20. #define F_SEEK_SET FILE_BEGIN
  21. BOOL NEAR PASCAL IsFAPI(int fh, struct new_exe FAR *pne, long off);
  22. /*
  23. * Function will return a specific piece of information from a new EXEHDR
  24. *
  25. * szFile - Path Name a new exe
  26. * pBuf - Buffer to place returned info
  27. * nBuf - Size of buffer in BYTES
  28. * fInfo - What info to get?
  29. *
  30. * GEI_MODNAME - Get module name
  31. * GEI_DESCRIPTION - Get description
  32. * GEI_FLAGS - Get EXEHDR flags
  33. *
  34. * returns: LOWORD = ne_magic, HIWORD = ne_exever
  35. * 0 if error
  36. */
  37. DWORD FAR PASCAL GetExeInfo(LPTSTR szFile, void FAR *pBuf, int nBuf, UINT fInfo)
  38. {
  39. HANDLE fh;
  40. DWORD off;
  41. DWORD dw;
  42. BYTE len;
  43. struct exe_hdr exehdr;
  44. struct new_exe newexe;
  45. fh = FOPEN(szFile);
  46. if (fh == INVALID_HANDLE_VALUE)
  47. {
  48. return FALSE;
  49. }
  50. if (FREAD(fh, &exehdr, sizeof(exehdr)) != sizeof(exehdr) ||
  51. exehdr.e_magic != EMAGIC ||
  52. exehdr.e_lfanew == 0L)
  53. {
  54. goto error; /* Abort("Not an exe",h); */
  55. }
  56. FSEEK(fh, exehdr.e_lfanew, F_SEEK_SET);
  57. if (FREAD(fh, &newexe, sizeof(newexe)) != sizeof(newexe))
  58. {
  59. goto error; // Read error
  60. }
  61. if (newexe.ne_magic == PEMAGIC)
  62. {
  63. if (fInfo != GEI_DESCRIPTION &&
  64. fInfo != GEI_EXPVER)
  65. goto error;
  66. // make the file name the description
  67. StringCchCopy((LPTSTR) pBuf, nBuf, szFile);
  68. // read the SubsystemVersion
  69. FSEEK(fh,exehdr.e_lfanew+18*4,F_SEEK_SET);
  70. FREAD(fh,&dw,4);
  71. newexe.ne_expver = LOBYTE(LOWORD(dw)) << 8 | LOBYTE(HIWORD(dw));
  72. goto exit;
  73. }
  74. if (newexe.ne_magic != NEMAGIC)
  75. {
  76. goto error; // Invalid NEWEXE
  77. }
  78. switch (fInfo)
  79. {
  80. case GEI_EXEHDR:
  81. *(struct new_exe *)pBuf = newexe;
  82. break;
  83. case GEI_FLAGS:
  84. *(WORD *)pBuf = newexe.ne_flags;
  85. break;
  86. /* module name is the first entry in the medident name table */
  87. case GEI_MODNAME:
  88. off = exehdr.e_lfanew + newexe.ne_restab;
  89. goto readstr;
  90. break;
  91. /* module name is the first entry in the non-medident name table */
  92. case GEI_DESCRIPTION:
  93. off = newexe.ne_nrestab;
  94. readstr:
  95. FSEEK(fh, off, F_SEEK_SET);
  96. FREAD(fh, &len, sizeof(BYTE));
  97. nBuf--; // leave room for a \0
  98. if (len > (BYTE)nBuf)
  99. len = (BYTE)nBuf;
  100. {
  101. LPSTR pbTmp;
  102. pbTmp = (LPSTR) LocalAlloc(LMEM_FIXED, len);
  103. if (pbTmp)
  104. {
  105. FREAD(fh, pbTmp, len);
  106. len = (BYTE)MultiByteToWideChar( CP_ACP, MB_PRECOMPOSED, pbTmp, len,
  107. (LPWSTR)pBuf, nBuf / sizeof(WCHAR));
  108. LocalFree(pbTmp);
  109. }
  110. }
  111. ((LPTSTR)pBuf)[len] = 0;
  112. break;
  113. case GEI_EXPVER:
  114. break;
  115. default:
  116. goto error;
  117. break;
  118. }
  119. exit:
  120. FCLOSE(fh);
  121. return MAKELONG(newexe.ne_magic, newexe.ne_expver);
  122. error:
  123. FCLOSE(fh);
  124. return 0;
  125. }
  126. // Code taken from kernel32.dll
  127. #define DEFAULT_WAIT_FOR_INPUT_IDLE_TIMEOUT 30000
  128. UINT WinExecN(LPCTSTR pszPath, LPTSTR pszPathAndArgs, UINT uCmdShow)
  129. {
  130. STARTUPINFO StartupInfo;
  131. PROCESS_INFORMATION ProcessInformation;
  132. BOOL CreateProcessStatus;
  133. DWORD ErrorCode;
  134. ZeroMemory(&StartupInfo,sizeof(StartupInfo));
  135. StartupInfo.cb = sizeof(StartupInfo);
  136. StartupInfo.dwFlags = STARTF_USESHOWWINDOW;
  137. StartupInfo.wShowWindow = (WORD)uCmdShow;
  138. CreateProcessStatus = CreateProcess(
  139. pszPath,
  140. pszPathAndArgs,
  141. NULL,
  142. NULL,
  143. FALSE,
  144. 0,
  145. NULL,
  146. NULL,
  147. &StartupInfo,
  148. &ProcessInformation
  149. );
  150. if ( CreateProcessStatus )
  151. {
  152. // Wait for the started process to go idle. If it doesn't go idle in
  153. // 10 seconds, return anyway.
  154. WaitForInputIdle(ProcessInformation.hProcess, DEFAULT_WAIT_FOR_INPUT_IDLE_TIMEOUT);
  155. CloseHandle(ProcessInformation.hProcess);
  156. CloseHandle(ProcessInformation.hThread);
  157. return 33;
  158. }
  159. else
  160. {
  161. // If CreateProcess failed, then look at GetLastError to determine
  162. // appropriate return code.
  163. ErrorCode = GetLastError();
  164. switch ( ErrorCode )
  165. {
  166. case ERROR_FILE_NOT_FOUND:
  167. return 2;
  168. case ERROR_PATH_NOT_FOUND:
  169. return 3;
  170. case ERROR_BAD_EXE_FORMAT:
  171. return 11;
  172. default:
  173. return 0;
  174. }
  175. }
  176. }