#include #include #include #include #include #include #pragma comment(lib, "Shlwapi") #ifdef _CONSOLE #pragma comment(linker, "/SUBSYSTEM:CONSOLE") #else #pragma comment(linker, "/SUBSYSTEM:WINDOWS") #endif #pragma comment(lib, "User32.lib") #define MAX_ENV 32767 #ifdef _CONSOLE #define die(...) do { fprintf(stderr , __VA_ARGS__); exit(1); } while (0) #else #define die(...) do { \ sprintf_s(diemsg, MAX_ENV, __VA_ARGS__); \ MessageBox(NULL, diemsg, "Error", MB_OK | MB_ICONERROR); \ exit(1); \ } while (0) char diemsg[MAX_ENV]; #endif #ifdef _CONSOLE int main(int argc, char *argv[]) { #else int WinMain(HINSTANCE inst, HINSTANCE previnst, LPSTR _cmdline, int show) { #endif TCHAR *args, *cmd, *cmdline, *file, *newcmdline, *p; TCHAR exefile[MAX_PATH+1], objfile[MAX_PATH+1]; TCHAR include[MAX_ENV+1], lib[MAX_ENV+1], path[MAX_ENV+1]; TCHAR vs[MAX_PATH+1], sdk[MAX_PATH+1]; DWORD attr, exitcode; FILETIME fwrite, cwrite; HANDLE fh, ch; PROCESS_INFORMATION pi; STARTUPINFO si; int i; cmdline = PathGetArgs(GetCommandLine()); if (cmdline[0] == '\0') #ifdef _CONSOLE die("%s: file [arguments ...]\n", argv[0]); #else die("No file provided.\n"); #endif newcmdline = malloc(1 + strlen(cmdline) * sizeof(char)); if (newcmdline == NULL) die("Could not allocate memory for command string\n"); strcpy(newcmdline, cmdline); for (; *newcmdline == ' '; newcmdline++) ; PathRemoveArgs(cmdline); if (cmdline[0] == '\0') strcpy(cmdline, newcmdline); file = cmdline; if (file[0] == '"') file++; if (file[strlen(file)-1] == '"') file[strlen(file)-1] = '\0'; if (strlen(file) + 1 > MAX_PATH) die("File path too long\n"); strcpy(exefile, file); strcpy(objfile, file); for (i = strlen(file); i > 0; i--) if (file[i] == '.') { i--; break; } else if (file[i] == '\\') { i = strlen(file) + 1; break; } strcpy(exefile + i + 1, ".exe"); strcpy(objfile + i + 1, ".obj"); done: ch = CreateFile(exefile, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); if (ch != INVALID_HANDLE_VALUE) { fh = CreateFile(file, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); if (fh == INVALID_HANDLE_VALUE) { if (GetLastError() == ERROR_FILE_NOT_FOUND) die("File not found: %s\n", file); else die("Could not open file (CreateFile failed with %d)\n", GetLastError()); } assert(GetFileTime(ch, NULL, NULL, &cwrite) != 0); assert(GetFileTime(fh, NULL, NULL, &fwrite) != 0); if (CompareFileTime(&fwrite, &cwrite) == -1) goto run; } CloseHandle(fh); CloseHandle(ch); #define set(var, val) \ if (SetEnvironmentVariable(var, val) == 0) \ die("Could not create environment variable"); include[0] = '\0'; lib[0] = '\0'; if (GetEnvironmentVariable("VSDIR", vs, MAX_PATH+1) != 0) { sprintf(include, "%s\\vc\\include", vs); sprintf(lib, "%s\\vc\\lib", vs); sprintf(path, "%s\\vc\\bin;%s\\Common7\\IDE", vs, vs); set("INCLUDE", include); set("LIB", lib); set("PATH", path); } if (GetEnvironmentVariable("SDKDIR", sdk, MAX_PATH+1) != 0) { sprintf(include + strlen(include), ";%s\\include", sdk); sprintf(lib + strlen(lib), ";%s\\lib", sdk); set("INCLUDE", include); set("LIB", lib); } DeleteFile(exefile); cmd = malloc(sizeof("cmd /k cl \"\" && exit 0") + strlen(file) * sizeof(char)); if (cmd == NULL) die("Could not allocate memory for command string\n"); #if _CONSOLE sprintf(cmd, "cmd /c cl \"%s\"", file); #else sprintf(cmd, "cmd /k cl \"%s\" && exit 0", file); #endif i = CreateProcess( NULL, cmd, NULL, NULL, FALSE, 0, NULL, NULL, // use parent's starting directory &si, &pi); if (i == 0) die("CreateProcess failed with %d\n", GetLastError()); WaitForSingleObject(pi.hProcess, INFINITE); GetExitCodeProcess(pi.hProcess, &exitcode); CloseHandle(pi.hProcess); CloseHandle(pi.hThread); DeleteFile(objfile); if (exitcode) { return exitcode; } printf("\n"); attr = GetFileAttributes(exefile); if ((attr & FILE_ATTRIBUTE_HIDDEN) == 0) SetFileAttributes(exefile, attr | FILE_ATTRIBUTE_HIDDEN); run: #ifndef _CONSOLE ZeroMemory(&si, sizeof(STARTUPINFO)); si.cb = sizeof(STARTUPINFO); si.dwFlags = STARTF_USESHOWWINDOW; si.wShowWindow = SW_HIDE; #endif i = CreateProcess( exefile, newcmdline, NULL, NULL, FALSE, 0, NULL, NULL, // use parent's starting directory &si, &pi); if (i == 0) die("CreateProcess failed with %d\n", GetLastError()); exitcode = 0; #ifdef _CONSOLE WaitForSingleObject(pi.hProcess, INFINITE); GetExitCodeProcess(pi.hProcess, &exitcode); #endif CloseHandle(pi.hProcess); CloseHandle(pi.hThread); return exitcode; }