nh_bool get_gamedir(enum game_dirs dirtype, wchar_t *buf) { wchar_t *subdir; wchar_t appPath[MAX_PATH], nhPath[MAX_PATH]; /* Get the location of "AppData\Roaming" (Vista, 7) or "Application Data" (XP). * The returned Path does not include a trailing backslash. */ if (!SUCCEEDED(SHGetFolderPath(NULL, CSIDL_APPDATA, NULL, 0, appPath))) return FALSE; switch (dirtype) { case CONFIG_DIR: subdir = L"\\"; break; case SAVE_DIR: subdir = L"\\save\\"; break; case LOG_DIR: subdir = L"\\log\\"; break; } snwprintf(nhPath, MAX_PATH, L"%s\\NitroHack", appPath); _wmkdir(nhPath); snwprintf(buf, BUFSZ, L"%s%s", nhPath, subdir); _wmkdir(buf); return TRUE; }
VOID UpdateGui(HWND hwnd, DWORD nConverted, DWORD nTotal, LPCWSTR lpLastConverted) { WCHAR szwTitle[256]; WCHAR szwProgress[256]; DWORD dwPercent = 0; dwPercent = (unsigned int)(((float)nConverted / (float)nTotal) * (float)100); snwprintf(szwTitle, sizeof(szwTitle) / sizeof(WCHAR)-1, TITLE_CONVERTING, dwPercent); snwprintf(szwProgress, sizeof(szwTitle) / sizeof(WCHAR)-1, MSG_CONVERTED, nConverted, nTotal); dialog_update_progress(hwnd, dwPercent, szwTitle, szwProgress, lpLastConverted); }
INT_PTR CALLBACK RangDialogProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { wchar_t tmpstr[MAXSETTINGSSTRLEN+100]; int i; switch (uMsg) { case WM_INITDIALOG: for (i=0;i<scores.n;++i) { snwprintf(tmpstr, MAXSETTINGSSTRLEN+100, L"%4d %s", scores.imena[i].bodova, scores.imena[i].ime); SendDlgItemMessage(hWnd, IDC_RANGLIST, LB_ADDSTRING, 0, (LPARAM)tmpstr); } break; case WM_COMMAND: switch (LOWORD(wParam)) { case IDCANCEL: case IDOK: EndDialog(hWnd, 0); break; case IDC_CLEARRANG: if (ClearRang(hWnd)) { SendDlgItemMessage(hWnd, IDC_RANGLIST, LB_RESETCONTENT, 0, 0); } break; } break; case WM_CLOSE: EndDialog(hWnd, 0); break; default: return FALSE; } return TRUE; }
void LogWriter::log(WCHAR *fmt, va_list args) { wstr_t logMessage = CLOCK.nowTimeWithMilliSec(); size_t threadId = GET_CURRENT_THREAD_ID(); logMessage += L"\t"; Thread *thread = ThreadManager::getInstance().at(threadId); if (thread) { logMessage += thread->name(); } else { logMessage += prefix_; } array<WCHAR, SIZE_8 * 2> threadIdStr; snwprintf(threadIdStr, L"0x%X", threadId); logMessage += L":"; logMessage += threadIdStr.data(); logMessage += L"\t"; array<WCHAR, SIZE_1024> logStr; vswprintf_s(logStr.data(), logStr.size(), fmt, args); logMessage += logStr.data(); logMessage += L"\n"; base_->log((WCHAR *)logMessage.c_str()); }
BOOL WritePrivateProfileIntW(LPCWSTR lpAppName, LPCWSTR lpKeyName, int val, LPCWSTR lpFileName) { wchar_t buf[12]; snwprintf(buf, 12, L"%d", val); return WritePrivateProfileStringW(lpAppName, lpKeyName, buf, lpFileName); }
void cpix_Error_report(cpix_Error * thisError, wchar_t * target, size_t targetLength) { if (thisError != NULL) { const wchar_t * errorTypeName = GetErrorTypeName(thisError->type_); const wchar_t * detail = thisError->msg_; if (detail == NULL) { detail = L"No details"; } snwprintf(target, targetLength, L"Error type: %S. %S\n", errorTypeName, detail); } else { *target = 0; } }
static const char *initerr(const char *message, const WCHAR *label, DWORD value) { WCHAR *sysmsg; BOOL hassysmsg; WCHAR *beforele; WCHAR *afterle; int n; WCHAR *wmessage; WCHAR *wstr; const char *str; if (FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, value, 0, (LPWSTR) (&sysmsg), 0, NULL) != 0) { hassysmsg = TRUE; beforele = L" ("; afterle = L")"; } else { hassysmsg = FALSE; sysmsg = L""; beforele = L""; afterle = L""; } wmessage = toUTF16(message); n = _scwprintf(initErrorFormat, initErrorArgs); wstr = (WCHAR *) uiAlloc((n + 1) * sizeof (WCHAR), "WCHAR[]"); snwprintf(wstr, n + 1, initErrorFormat, initErrorArgs); str = toUTF8(wstr); uiFree(wstr); if (hassysmsg) if (LocalFree(sysmsg) != NULL) logLastError("error freeing system message in loadLastError()"); uiFree(wmessage); return str; }
void rungame(void) { int ret, role = initrole, race = initrace, gend = initgend, align = initalign; int fd = -1; char plname[BUFSZ]; fnchar filename[1024]; fnchar savedir[BUFSZ]; long t; if (!get_gamedir(SAVE_DIR, savedir)) { curses_raw_print("Could not find where to put the logfile for a new game."); return; } if (!player_selection(&role, &race, &gend, &align, random_player)) return; strncpy(plname, settings.plname, PL_NSIZ); /* The player name is set to "wizard" (again) in nh_start_game, so setting * it here just prevents wizmode player from being asked for a name. */ if (ui_flags.playmode == MODE_WIZARD) strcpy(plname, "wizard"); while (!plname[0]) curses_getline("what is your name?", plname); if (plname[0] == '\033') /* canceled */ return; t = (long)time(NULL); #if defined(WIN32) snwprintf(filename, 1024, L"%ls%ld_%hs.nhgame", savedir, t, plname); #else snprintf(filename, 1024, "%s%ld_%s.nhgame", savedir, t, plname); #endif fd = sys_open(filename, O_TRUNC | O_CREAT | O_RDWR, FILE_OPEN_MASK); if (fd == -1) { curses_raw_print("Could not create the logfile."); return; } create_game_windows(); if (!nh_start_game(fd, plname, role, race, gend, align, ui_flags.playmode)) { destroy_game_windows(); close(fd); return; } load_keymap(); /* need to load the keymap after the game has been started */ ret = commandloop(); free_keymap(); close(fd); destroy_game_windows(); cleanup_messages(); game_ended(ret, filename); }
int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpszCmdLine, int nCmdShow) { /* support for auto answering based on words in the assertion. * the assertion message is sent as a series of arguements (words) to the commandline. * set a "word" to 0xffffffff to let the word not affect this code. * set a "word" to 0xfffffffe to show the dialog. * set a "word" to 0x5 to ignore (program should continue). * set a "word" to 0x4 to retry (should fall into debugger). * set a "word" to 0x3 to abort (die). */ DWORD regType; DWORD regValue = -1; DWORD regLength = sizeof regValue; HKEY hkeyCU, hkeyLM; RegOpenKeyExW(HKEY_CURRENT_USER, L"Software\\mozilla.org\\windbgdlg", 0, KEY_READ, &hkeyCU); RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"Software\\mozilla.org\\windbgdlg", 0, KEY_READ, &hkeyLM); int argc =0; for (int i = __argc - 1; regValue == (DWORD)-1 && i; --i) { bool ok = false; if (hkeyCU) ok = RegQueryValueExW(hkeyCU, __wargv[i], 0, ®Type, (LPBYTE)®Value, ®Length) == ERROR_SUCCESS; if (!ok && hkeyLM) ok = RegQueryValueExW(hkeyLM, __wargv[i], 0, ®Type, (LPBYTE)®Value, ®Length) == ERROR_SUCCESS; if (!ok) regValue = -1; } if (hkeyCU) RegCloseKey(hkeyCU); if (hkeyLM) RegCloseKey(hkeyLM); if (regValue != (DWORD)-1 && regValue != (DWORD)-2) return regValue; static const int size = 4096; static WCHAR msg[size]; #ifdef _MSC_VER StringCchPrintfW(msg, #else snwprintf(msg, #endif size, L"%s\n\nClick Abort to exit the Application.\n" L"Click Retry to Debug the Application.\n" L"Click Ignore to continue running the Application.", lpszCmdLine); msg[size - 1] = L'\0'; return MessageBoxW(nullptr, msg, L"NSGlue_Assertion", MB_ICONSTOP | MB_SYSTEMMODAL | MB_ABORTRETRYIGNORE | MB_DEFBUTTON3); }
int broker_os_add_qpid_route_link(const char *local, const char *remote) { wchar_t cmd[1024]; snwprintf(cmd, sizeof(cmd) / sizeof(*cmd), L"%ls link add %s untrusted/untrusted@%s PLAIN", QPID_ROUTE, local, remote); if (start_process(QPID_ROUTE, cmd)) { return -1; } return 0; }
string ChatCtrl::escapeUnicode(tstring str) { TCHAR buf[8]; memzero(buf, sizeof(buf)); int dist = 0; tstring::iterator i; while((i = std::find_if(str.begin() + dist, str.end(), std::bind2nd(std::greater<TCHAR>(), 0x7f))) != str.end()) { dist = (i+1) - str.begin(); // Random Acess iterators FTW snwprintf(buf, sizeof(buf), _T("%hd"), int(*i)); str.replace(i, i+1, _T("\\ud\\u") + tstring(buf) + _T("?")); memzero(buf, sizeof(buf)); } return Text::fromT(str); }
int broker_os_add_qpid_route(const struct mh_qpid_route *route) { wchar_t cmd[1024]; if (route->aggregate && route->srclocal) { snwprintf(cmd, sizeof(cmd) / sizeof(*cmd), L"%ls --src-local route add %s %s %s %s", QPID_ROUTE, route->dest, route->src, route->exchange, route->route_key); } else if (route->aggregate) { snwprintf(cmd, sizeof(cmd) / sizeof(*cmd), L"%ls route add %s %s %s %s", QPID_ROUTE, route->dest, route->src, route->exchange, route->route_key); } else { snwprintf(cmd, sizeof(cmd) / sizeof(*cmd), L"%ls --timeout=5 dynamic add %s %s %s", QPID_ROUTE, route->dest, route->src, route->exchange); } if (start_process(QPID_ROUTE, cmd)) { return -1; } return 0; }
void print(const wchar_t* format, ...) { wchar_t buffer[1024]; va_list vl; static std::size_t line = 0; line++; snwprintf(buffer, 5, L"%03d:", line); va_start(vl, format); vsnwprintf(buffer + 5, 1023 - 5, format, vl); va_end(vl); buffer[4] = L' '; buffer[1023] = L'\0'; OutputDebugStringW(buffer); }
HANDLE capture_mutex(char *name) { wchar_t namew[MAX_PATH]; snwprintf(namew,MAX_PATH,L"%S",name); UNICODE_STRING uniname; RtlInitUnicodeString(&uniname,namew); OBJECT_ATTRIBUTES oa; InitializeObjectAttributes(&oa,&uniname,OBJ_CASE_INSENSITIVE | OBJ_OPENIF,0,NULL); HANDLE mutex; DWORD access=MUTANT_ALL_ACCESS; NTSTATUS status=ZwOpenMutant(&mutex,access,&oa); if (!NT_SUCCESS(status)) return 0; printf("Mutex opened.\n"); if (WaitForSingleObject(mutex,5000)==WAIT_OBJECT_0) return mutex; ZwClose(mutex); return NULL; }
int broker_os_start_broker(char * const args[]) { int ret; wchar_t cmdline[CMD_LINE_LENGTH]; int i = 0; const char *arg; for (arg = *args; arg; arg++) { int c = snwprintf(cmdline + i, CMD_LINE_LENGTH - i, L"%s ", arg); if (c < 0 || (i += c) >= (CMD_LINE_LENGTH - 1)) { return -1; } } ret = start_process(QPID_BROKER, cmdline); broker_federation_configure(); return ret ? -1 : 0; }
/* * Check workdir\fname is inside config_dir * The logic here is simple: we may reject some valid paths if ..\ is in any of the strings */ static BOOL CheckConfigPath(const WCHAR *workdir, const WCHAR *fname, const settings_t *s) { WCHAR tmp[MAX_PATH]; const WCHAR *config_file = NULL; const WCHAR *config_dir = NULL; /* convert fname to full path */ if (PathIsRelativeW(fname) ) { snwprintf(tmp, _countof(tmp), L"%s\\%s", workdir, fname); tmp[_countof(tmp)-1] = L'\0'; config_file = tmp; } else { config_file = fname; } #ifdef UNICODE config_dir = s->config_dir; #else if (MultiByteToWideChar(CP_UTF8, 0, s->config_dir, -1, widepath, MAX_PATH) == 0) { MsgToEventLog(M_SYSERR, TEXT("Failed to convert config_dir name to WideChar")); return FALSE; } config_dir = widepath; #endif if (wcsncmp(config_dir, config_file, wcslen(config_dir)) == 0 && wcsstr(config_file + wcslen(config_dir), L"..") == NULL) { return TRUE; } return FALSE; }
int convert_to_roe(const wchar_t *src_path, const wchar_t *filename, const wchar_t *dest_path, convert_cb_t cb, void *cb_data) { h3mlib_ctx_t h3m = NULL; wchar_t fullpath[MAX_PATH] = { 0 }; wchar_t fullpath_out[MAX_PATH] = { 0 }; wchar_t fullpath_patch[MAX_PATH] = { 0 }; wchar_t *version = L"unknown"; enum H3M_FORMAT fm_src = 0; int ret = 0; snwprintf(fullpath, sizeof(fullpath) / sizeof(fullpath[0])-1, L"%s\\%s", src_path, filename); h3m_read_convert_u(&h3m, fullpath, H3M_FORMAT_ROE, &fm_src, NULL, NULL, NULL, NULL); if (NULL == h3m) { if (NULL != cb) { if (0 != (ret = cb(filename, fm_src, (H3M_FORMAT_ROE != fm_src) ? CONVERT_RESULT_FAIL : CONVERT_RESULT_SKIP, cb_data))) { return ret; } } return 0; } switch (fm_src) { case H3M_FORMAT_AB: version = L"AB"; break; case H3M_FORMAT_SOD: version = L"SoD"; break; case H3M_FORMAT_WOG: version = L"WoG"; break; default: version = L"??"; } snwprintf(fullpath_out, sizeof(fullpath_out) / sizeof(fullpath_out[0])-1, L"%s\\[%s-RoE] %s", dest_path, version, filename); snwprintf(fullpath_patch, sizeof(fullpath_patch)-sizeof(fullpath_patch[0]) - 1, L"h3mpatches\\patch_%s", filename); if (INVALID_FILE_ATTRIBUTES != GetFileAttributesW(fullpath_patch)) { h3m_object_patch_u(h3m, fullpath_patch); } h3m_write_u(h3m, fullpath_out); //h3m_compress(fullpath_out, fullpath_out); h3m_exit(&h3m); if (NULL != cb) { if (0 != (ret = cb(filename, fm_src, CONVERT_RESULT_SUCCESS, cb_data))) { return ret; } } return 0; }
/* FIXME - like inject_into_thread we assume esp, but we could allocate our * own stack in the child and swap to that for transparency. */ bool inject_into_new_process(HANDLE phandle, char *dynamo_path, bool map, uint inject_location, void *inject_address) { void *hook_target = NULL, *hook_location = NULL; uint old_prot; size_t num_bytes_out; byte hook_buf[5]; /* Possible child hook points */ GET_NTDLL(KiUserApcDispatcher, (IN PVOID Unknown1, IN PVOID Unknown2, IN PVOID Unknown3, IN PVOID ContextStart, IN PVOID ContextBody)); GET_NTDLL(KiUserExceptionDispatcher, (IN PVOID Unknown1, IN PVOID Unknown2)); /* Only ones that work, though I have hopes for KiUserException if can * find a better spot to trigger the exception, or we should implement * KiUserApc map requirement. */ ASSERT_NOT_IMPLEMENTED(INJECT_LOCATION_IS_LDR(inject_location)); switch(inject_location) { case INJECT_LOCATION_LdrLoadDll: case INJECT_LOCATION_LdrpLoadDll: case INJECT_LOCATION_LdrCustom: case INJECT_LOCATION_LdrpLoadImportModule: case INJECT_LOCATION_LdrDefault: /* caller provides the ldr address to use */ ASSERT(inject_address != NULL); hook_location = inject_address; if (hook_location == NULL) { goto error; } break; case INJECT_LOCATION_KiUserApc: hook_location = (void *)KiUserApcDispatcher; ASSERT(map); break; case INJECT_LOCATION_KiUserException: hook_location = (void *)KiUserExceptionDispatcher; break; default: ASSERT_NOT_REACHED(); goto error; } /* read in code at hook */ if (!nt_read_virtual_memory(phandle, hook_location, hook_buf, sizeof(hook_buf), &num_bytes_out) || num_bytes_out != sizeof(hook_buf)) { goto error; } if (map) { hook_target = NULL; /* for compiler */ /* NYI see case 102, plan is to remote map in our dll, link and rebase if * necessary and hook to a routine in our dll */ ASSERT_NOT_IMPLEMENTED(false); } else { byte *remote_code_buffer = NULL, *remote_data_buffer; /* max usage for local_buf is for writing the dr library name * 2*MAX_PATH (unicode) + sizoef(UNICODE_STRING) + 2, round up to * 3*MAX_PATH to be safe */ byte local_buf[3*MAX_PATH]; byte *cur_local_pos, *cur_remote_pos, *jmp_fixup1, *jmp_fixup2; char *takeover_func = "dynamorio_app_init_and_early_takeover"; PUNICODE_STRING mod, mod_remote; PANSI_STRING func, func_remote; int res; size_t num_bytes_in; GET_NTDLL(LdrLoadDll, (IN PCWSTR PathToFile OPTIONAL, IN PULONG Flags OPTIONAL, IN PUNICODE_STRING ModuleFileName, OUT PHANDLE ModuleHandle)); GET_NTDLL(LdrGetProcedureAddress, (IN HANDLE ModuleHandle, IN PANSI_STRING ProcedureName OPTIONAL, IN ULONG Ordinal OPTIONAL, OUT FARPROC *ProcedureAddress)); #define GET_PROC_ADDR_BAD_ADDR 0xffbadd11 GET_NTDLL(NtProtectVirtualMemory, (IN HANDLE ProcessHandle, IN OUT PVOID *BaseAddress, IN OUT PULONG ProtectSize, IN ULONG NewProtect, OUT PULONG OldProtect)); GET_NTDLL(NtContinue, (IN PCONTEXT Context, IN BOOLEAN TestAlert)); /* get buffer for emitted code and data */ if (!NT_SUCCESS(nt_remote_allocate_virtual_memory(phandle, &remote_code_buffer, 2*PAGE_SIZE, PAGE_READWRITE, MEM_COMMIT))) { goto error; } remote_data_buffer = remote_code_buffer + PAGE_SIZE; /* write data */ /* FIXME the two writes are similar (unicode vs ascii), could combine */ /* First UNICODE_STRING to library */ cur_remote_pos = remote_data_buffer; cur_local_pos = local_buf; ASSERT_ROOM(cur_local_pos, local_buf, sizeof(UNICODE_STRING)); mod = (PUNICODE_STRING)cur_local_pos; memset(mod, 0, sizeof(UNICODE_STRING)); cur_local_pos += sizeof(UNICODE_STRING); mod->Buffer = (wchar_t *)(cur_remote_pos + (cur_local_pos - local_buf)); ASSERT_ROOM(cur_local_pos, local_buf, 2*MAX_PATH+2 /* plus null */); res = snwprintf((wchar_t *)cur_local_pos, 2*MAX_PATH, L"%hs", dynamo_path); ASSERT(res > 0); if (res > 0) { cur_local_pos += (2*res); ASSERT_TRUNCATE(mod->Length, ushort, 2*res); mod->Length = (ushort)(2*res); mod->MaximumLength = (ushort)(2*res); } /* ensure NULL termination, just in case */ *(wchar_t *)cur_local_pos = L'\0'; cur_local_pos += sizeof(wchar_t); /* write to remote process */ num_bytes_in = cur_local_pos - local_buf; if (!nt_write_virtual_memory(phandle, cur_remote_pos, local_buf, num_bytes_in, &num_bytes_out) || num_bytes_out != num_bytes_in) { goto error; } mod_remote = (PUNICODE_STRING)cur_remote_pos; cur_remote_pos += num_bytes_out; /* now write init/takeover func */ cur_local_pos = local_buf; ASSERT_ROOM(cur_local_pos, local_buf, sizeof(ANSI_STRING)); func = (PANSI_STRING)cur_local_pos; memset(func, 0, sizeof(ANSI_STRING)); cur_local_pos += sizeof(ANSI_STRING); func->Buffer = (PCHAR) cur_remote_pos + (cur_local_pos - local_buf); ASSERT_ROOM(cur_local_pos, local_buf, strlen(takeover_func)+1); strncpy((char *)cur_local_pos, takeover_func, strlen(takeover_func)); cur_local_pos += strlen(takeover_func); ASSERT_TRUNCATE(func->Length, ushort, strlen(takeover_func)); func->Length = (ushort)strlen(takeover_func); func->MaximumLength = (ushort)strlen(takeover_func); *cur_local_pos++ = '\0'; /* ensure NULL termination, just in case */ /* write to remote_process */ num_bytes_in = cur_local_pos - local_buf; if (!nt_write_virtual_memory(phandle, cur_remote_pos, local_buf, num_bytes_in, &num_bytes_out) || num_bytes_out != num_bytes_in) { goto error; } func_remote = (PANSI_STRING)cur_remote_pos; cur_remote_pos += num_bytes_out; /* now make data page read only */ res = nt_remote_protect_virtual_memory(phandle, remote_data_buffer, PAGE_SIZE, PAGE_READONLY, &old_prot); ASSERT(res); #define INSERT_INT(value) \ *(int *)cur_local_pos = value; \ cur_local_pos += sizeof(int) #define PUSH_IMMEDIATE(value) \ *cur_local_pos++ = PUSH_IMM32; \ INSERT_INT(value) #define PUSH_SHORT_IMMEDIATE(value) \ *cur_local_pos++ = PUSH_IMM8; \ *cur_local_pos++ = value #define MOV_ESP_TO_EAX() \ *cur_local_pos++ = MOV_RM32_2_REG32; \ *cur_local_pos++ = MOV_ESP_2_EAX_RM /* FIXME - all values are small use imm8 version */ #define ADD_TO_EAX(value) \ *cur_local_pos++ = ADD_EAX_IMM32; \ INSERT_INT(value) #define INSERT_REL32_ADDRESS(target) \ IF_X64(ASSERT_NOT_IMPLEMENTED(false)); \ INSERT_INT((int)(ptr_int_t)((byte *)target - \ (((cur_local_pos - local_buf)+4)+cur_remote_pos))) #define CALL(target_func) \ *cur_local_pos++ = CALL_REL32; \ INSERT_REL32_ADDRESS(target_func) /* ecx will hold OldProtection afterwards */ #define PROT_IN_ECX 0xbad15bad /* doesn't match a PAGE_* define */ #define CHANGE_PROTECTION(start, size, new_protection) \ *cur_local_pos++ = PUSH_EAX; /* OldProtect slot */ \ MOV_ESP_TO_EAX(); /* get &OldProtect */ \ IF_X64(ASSERT_NOT_IMPLEMENTED(false)); \ PUSH_IMMEDIATE((int)(ALIGN_FORWARD(start+size, PAGE_SIZE) - \ ALIGN_BACKWARD(start, PAGE_SIZE))); /* ProtectSize */ \ PUSH_IMMEDIATE((int)ALIGN_BACKWARD(start, PAGE_SIZE)); /* BaseAddress */ \ *cur_local_pos++ = PUSH_EAX; /* arg 5 &OldProtect */ \ if (new_protection == PROT_IN_ECX) { \ *cur_local_pos++ = PUSH_ECX; /* arg 4 NewProtect */ \ } else { \ PUSH_IMMEDIATE(new_protection); /* arg 4 NewProtect */ \ } \ ADD_TO_EAX(-4); /* get &ProtectSize */ \ *cur_local_pos++ = PUSH_EAX; /* arg 3 &ProtectSize */ \ ADD_TO_EAX(-4); /* get &BaseAddress */ \ *cur_local_pos++ = PUSH_EAX; /* arg 2 &BaseAddress */ \ PUSH_IMMEDIATE((int)(ptr_int_t)NT_CURRENT_PROCESS); /* arg ProcessHandle */ \ CALL(NtProtectVirtualMemory); \ /* no error checking, can't really do anything about it, FIXME */ \ /* stdcall so just the three slots we made for the ptr arguments \ * left on the stack */ \ *cur_local_pos++ = POP_ECX; /* pop BaseAddress */ \ *cur_local_pos++ = POP_ECX; /* pop ProtectSize */ \ *cur_local_pos++ = POP_ECX /* pop OldProtect into ecx */ /* write code */ /* xref case 3821, first call to a possibly hooked routine should be * more then 5 bytes into the page, which is satisfied (though is not * clear if any hookers would manage to get in first). */ cur_remote_pos = remote_code_buffer; cur_local_pos = local_buf; hook_target = cur_remote_pos; /* for inject_location INJECT_LOCATION_Ldr* we stick the address used * at the start of the code for the child's use */ if (INJECT_LOCATION_IS_LDR(inject_location)) { IF_X64(ASSERT_NOT_IMPLEMENTED(false)); INSERT_INT((int)(ptr_int_t)inject_address); hook_target = cur_remote_pos + 4; /* skip the address */ } #if DEBUG_LOOP *cur_local_pos++ = JMP_REL8; *cur_local_pos++ = 0xfe; #endif /* save current state */ *cur_local_pos++ = PUSHA; *cur_local_pos++ = PUSHF; /* restore trampoline, first make writable */ CHANGE_PROTECTION(hook_location, 5, PAGE_EXECUTE_READWRITE); *cur_local_pos++ = MOV_IMM32_2_RM32; /* restore first 4 bytes of hook */ *cur_local_pos++ = MOV_IMM_RM_ABS; IF_X64(ASSERT_NOT_IMPLEMENTED(false)); INSERT_INT((int)(ptr_int_t)hook_location); INSERT_INT(*(int *)hook_buf); *cur_local_pos++ = MOV_IMM8_2_RM8; /* restore 5th byte of the hook */ *cur_local_pos++ = MOV_IMM_RM_ABS; IF_X64(ASSERT_NOT_IMPLEMENTED(false)); INSERT_INT((int)(ptr_int_t)hook_location+4); *cur_local_pos++ = hook_buf[4]; /* hook restored, restore protection */ CHANGE_PROTECTION(hook_location, 5, PROT_IN_ECX); if (inject_location == INJECT_LOCATION_KiUserException) { /* Making the first page of the image unreadable triggers an exception * to early to use the loader, might try pointing the import table ptr * to bad memory instead TOTRY, whatever we do should fixup here */ ASSERT_NOT_IMPLEMENTED(false); } /* call LdrLoadDll to load dr library */ *cur_local_pos++ = PUSH_EAX; /* need slot for OUT hmodule*/ MOV_ESP_TO_EAX(); *cur_local_pos++ = PUSH_EAX; /* arg 4 OUT *hmodule */ IF_X64(ASSERT_NOT_IMPLEMENTED(false)); PUSH_IMMEDIATE((int)(ptr_int_t)mod_remote); /* our library name */ PUSH_SHORT_IMMEDIATE(0x0); /* Flags OPTIONAL */ PUSH_SHORT_IMMEDIATE(0x0); /* PathToFile OPTIONAL */ CALL(LdrLoadDll); /* see signature at decleration above */ /* stdcall so removed args so top of stack is now the slot containing the * returned handle. Use LdrGetProcedureAddress to get the address of the * dr init and takeover function. Is ok to call even if LdrLoadDll failed, * so we check for errors afterwards. */ *cur_local_pos++ = POP_ECX; /* dr module handle */ *cur_local_pos++ = PUSH_ECX; /* need slot for out ProcedureAddress */ MOV_ESP_TO_EAX(); *cur_local_pos++ = PUSH_EAX; /* arg 4 OUT *ProcedureAddress */ PUSH_SHORT_IMMEDIATE(0x0); /* Ordinal OPTIONAL */ IF_X64(ASSERT_NOT_IMPLEMENTED(false)); PUSH_IMMEDIATE((int)(ptr_int_t)func_remote); /* func name */ *cur_local_pos++ = PUSH_ECX; /* module handle */ CALL(LdrGetProcedureAddress); /* see signature at decleration above */ /* Top of stack is now the dr init and takeover function (stdcall removed * args). Check for errors and bail (FIXME debug build report somehow?) */ *cur_local_pos++ = CMP_EAX_IMM32; INSERT_INT(STATUS_SUCCESS); *cur_local_pos++ = POP_EAX; /* dr init_and_takeover function */ *cur_local_pos++ = JNZ_REL8; /* FIXME - should check >= 0 instead? */ jmp_fixup1 = cur_local_pos++; /* jmp to after call below */ /* Xref case 8373, LdrGetProcedureAdderss sometimes returns an * address of 0xffbadd11 even though it returned STATUS_SUCCESS */ *cur_local_pos++ = CMP_EAX_IMM32; INSERT_INT(GET_PROC_ADDR_BAD_ADDR); *cur_local_pos++ = JZ_REL8; /* JZ == JE */ jmp_fixup2 = cur_local_pos++; /* jmp to after call below */ IF_X64(ASSERT_NOT_IMPLEMENTED(false)); PUSH_IMMEDIATE((int)(ptr_int_t)remote_code_buffer); /* arg to takeover func */ PUSH_IMMEDIATE(inject_location); /* arg to takeover func */ *cur_local_pos++ = CALL_RM32; /* call EAX */ *cur_local_pos++ = CALL_EAX_RM; *cur_local_pos++ = POP_ECX; /* cdecl so pop arg */ *cur_local_pos++ = POP_ECX; /* cdecl so pop arg */ /* Now patch the jnz above (if error) to go to here */ ASSERT_TRUNCATE(*jmp_fixup1, byte, cur_local_pos - (jmp_fixup1+1)); *jmp_fixup1 = (byte)(cur_local_pos - (jmp_fixup1+1)); /* target of jnz */ ASSERT_TRUNCATE(*jmp_fixup2, byte, cur_local_pos - (jmp_fixup2+1)); *jmp_fixup2 = (byte)(cur_local_pos - (jmp_fixup2+1)); /* target of jz */ *cur_local_pos++ = POPF; *cur_local_pos++ = POPA; if (inject_location != INJECT_LOCATION_KiUserException) { /* jmp back to the hook location to resume execution */ *cur_local_pos++ = JMP_REL32; INSERT_REL32_ADDRESS(hook_location); } else { /* we triggered the exception, so do an NtContinue back */ /* see callback.c, esp+4 holds CONTEXT ** */ *cur_local_pos++ = POP_EAX; /* EXCEPTION_RECORD ** */ *cur_local_pos++ = POP_EAX; /* CONTEXT ** */ PUSH_SHORT_IMMEDIATE(FALSE); /* arg 2 TestAlert */ *cur_local_pos++ = MOV_RM32_2_REG32; *cur_local_pos++ = MOV_derefEAX_2_EAX_RM; /* CONTEXT * -> EAX */ *cur_local_pos++ = PUSH_EAX; /* push CONTEXT * (arg 1) */ CALL(NtContinue); /* should never get here, will be zeroed memory so will crash if * we do happen to get here, good enough reporting */ } /* Our emitted code above is much less then the sizeof local_buf, * but we'll add a check here (after the fact so not robust if really * overflowed) that we didn't even come close (someon adding large amounts * of code should hit this. FIXME - do better? */ ASSERT_ROOM(cur_local_pos, local_buf, MAX_PATH); num_bytes_in = cur_local_pos - local_buf; if (!nt_write_virtual_memory(phandle, cur_remote_pos, local_buf, num_bytes_in, &num_bytes_out) || num_bytes_out != num_bytes_in) { goto error; } cur_remote_pos += num_bytes_out; /* now make code page rx */ res = nt_remote_protect_virtual_memory(phandle, remote_code_buffer, PAGE_SIZE, PAGE_EXECUTE_READ, &old_prot); ASSERT(res); #undef INSERT_INT #undef PUSH_IMMEDIATE #undef PUSH_SHORT_IMMEDIATE #undef MOV_ESP_TO_EAX #undef ADD_TO_EAX #undef INSERT_REL32_ADDRESS #undef CALL #undef PROT_IN_ECX #undef CHANGE_PROTECTION } /* place hook */ ASSERT(sizeof(hook_buf) == 5); /* standard 5 byte jmp rel32 hook */ hook_buf[0] = JMP_REL32; IF_X64(ASSERT_NOT_IMPLEMENTED(false)); *(int *)(&hook_buf[1]) = (int)((byte *)hook_target - ((byte *)hook_location + 5)); if (!nt_remote_protect_virtual_memory(phandle, hook_location, sizeof(hook_buf), PAGE_EXECUTE_READWRITE, &old_prot)) { goto error; } if (!nt_write_virtual_memory(phandle, hook_location, hook_buf, sizeof(hook_buf), &num_bytes_out) || num_bytes_out != sizeof(hook_buf)) { goto error; } if (!nt_remote_protect_virtual_memory(phandle, hook_location, sizeof(hook_buf), old_prot, &old_prot)) { goto error; } return true; error: /* we do not recover any changes in the child's address space */ return false; }
int wmain(int argc, wchar_t **argv) { // having these declarations at the start of the function is only needed for C compatibility int i; int soutBufferSize; int nr; char **vlc_argv; wchar_t *soutOption; wchar_t *config; wchar_t *path; libvlc_instance_t *vlc; libvlc_media_t *media; libvlc_media_player_t *player; libvlc_event_manager_t *eventManager; // init arguments if(argc < 3) { fwprintf(stdout, ENDLN(L"Usage: vlcwrapper <input> <soutstring> [optional vlc arguments]")); return 1; } // print some information path = argv[1]; config = argv[2]; fwprintf(stdout, ENDLN(L"I VLCWrapper version %s, using VLC %hs"), VERSION, libvlc_get_version()); fwprintf(stdout, ENDLN(L"A path %s"), path); fwprintf(stdout, ENDLN(L"A config %s"), config); // init state machine global_state = STATE_NULL; // arguments (you shouldn't need these in normal usage; but we don't support all arguments by ourself yet) nr = argc - 3; vlc_argv = (char**)malloc(nr * sizeof(char*)); for(i = 3; i < argc; i++) { fwprintf(stdout, ENDLN(L"A cmd %d %s"), i - 3, argv[i]); vlc_argv[i - 3] = to_utf8(argv[i]); } // init vlc vlc = libvlc_new(nr, vlc_argv); libvlc_set_user_agent(vlc, to_utf8(USER_AGENT), to_utf8(HTTP_USER_AGENT)); // create media and set sout string media = libvlc_media_new_path(vlc, to_utf8(path)); soutBufferSize = wcslen(config) + 6; soutOption = (wchar_t*)malloc(soutBufferSize * sizeof(wchar_t)); snwprintf(soutOption, soutBufferSize, soutBufferSize, L"sout=%s", config); libvlc_media_add_option(media, to_utf8(soutOption)); // create player and listen for events player = libvlc_media_player_new_from_media(media); eventManager = libvlc_media_player_event_manager(player); register_event(eventManager, libvlc_MediaPlayerPlaying, STATE_PLAYING); register_event(eventManager, libvlc_MediaPlayerEncounteredError, STATE_ERROR); register_event(eventManager, libvlc_MediaPlayerEndReached, STATE_FINISHED); // start playing it libvlc_media_player_play(player); // wait till it's started or stopped because of an error while(global_state != STATE_ERROR && global_state != STATE_PLAYING) millisleep(100); // let it play till it has finished, while printing status information while(global_state == STATE_PLAYING) { fwprintf(stdout, ENDLN(L"P %d"), libvlc_media_player_get_time(player)); fflush(stdout); millisleep(LOG_INTERVAL); } // stop playing libvlc_media_player_stop(player); // release objects in memory libvlc_media_release(media); libvlc_media_player_release(player); libvlc_release(vlc); return 0; }
int launch_server(const std::string& socket_spec) { #if defined(_WIN32) /* we need to start the server in the background */ /* we create a PIPE that will be used to wait for the server's "OK" */ /* message since the pipe handles must be inheritable, we use a */ /* security attribute */ SECURITY_ATTRIBUTES sa; sa.nLength = sizeof(sa); sa.lpSecurityDescriptor = NULL; sa.bInheritHandle = TRUE; // Redirect stdin to Windows /dev/null. If we instead pass an original // stdin/stdout/stderr handle and it is a console handle, when the adb // server starts up, the C Runtime will see a console handle for a process // that isn't connected to a console and it will configure // stdin/stdout/stderr to be closed. At that point, freopen() could be used // to reopen stderr/out, but it would take more massaging to fixup the file // descriptor number that freopen() uses. It's simplest to avoid all of this // complexity by just redirecting stdin to `nul' and then the C Runtime acts // as expected. unique_handle nul_read(CreateFileW(L"nul", GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, &sa, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL)); if (nul_read.get() == INVALID_HANDLE_VALUE) { fprintf(stderr, "Cannot open 'nul': %s\n", android::base::SystemErrorCodeToString(GetLastError()).c_str()); return -1; } // Create pipes with non-inheritable read handle, inheritable write handle. We need to connect // the subprocess to pipes instead of just letting the subprocess inherit our existing // stdout/stderr handles because a DETACHED_PROCESS cannot write to a console that it is not // attached to. unique_handle ack_read, ack_write; if (!_create_anonymous_pipe(&ack_read, &ack_write, &sa)) { return -1; } unique_handle stdout_read, stdout_write; if (!_create_anonymous_pipe(&stdout_read, &stdout_write, &sa)) { return -1; } unique_handle stderr_read, stderr_write; if (!_create_anonymous_pipe(&stderr_read, &stderr_write, &sa)) { return -1; } /* Some programs want to launch an adb command and collect its output by * calling CreateProcess with inheritable stdout/stderr handles, then * using read() to get its output. When this happens, the stdout/stderr * handles passed to the adb client process will also be inheritable. * When starting the adb server here, care must be taken to reset them * to non-inheritable. * Otherwise, something bad happens: even if the adb command completes, * the calling process is stuck while read()-ing from the stdout/stderr * descriptors, because they're connected to corresponding handles in the * adb server process (even if the latter never uses/writes to them). * Note that even if we don't pass these handles in the STARTUPINFO struct, * if they're marked inheritable, they're still inherited, requiring us to * deal with this. * * If we're still having problems with inheriting random handles in the * future, consider using PROC_THREAD_ATTRIBUTE_HANDLE_LIST to explicitly * specify which handles should be inherited: http://blogs.msdn.com/b/oldnewthing/archive/2011/12/16/10248328.aspx * * Older versions of Windows return console pseudo-handles that cannot be * made non-inheritable, so ignore those failures. */ _try_make_handle_noninheritable(GetStdHandle(STD_INPUT_HANDLE)); _try_make_handle_noninheritable(GetStdHandle(STD_OUTPUT_HANDLE)); _try_make_handle_noninheritable(GetStdHandle(STD_ERROR_HANDLE)); STARTUPINFOW startup; ZeroMemory( &startup, sizeof(startup) ); startup.cb = sizeof(startup); startup.hStdInput = nul_read.get(); startup.hStdOutput = stdout_write.get(); startup.hStdError = stderr_write.get(); startup.dwFlags = STARTF_USESTDHANDLES; // Verify that the pipe_write handle value can be passed on the command line // as %d and that the rest of adb code can pass it around in an int. const int ack_write_as_int = cast_handle_to_int(ack_write.get()); if (cast_int_to_handle(ack_write_as_int) != ack_write.get()) { // If this fires, either handle values are larger than 32-bits or else // there is a bug in our casting. // https://msdn.microsoft.com/en-us/library/windows/desktop/aa384203%28v=vs.85%29.aspx fprintf(stderr, "Cannot fit pipe handle value into 32-bits: 0x%p\n", ack_write.get()); return -1; } // get path of current program WCHAR program_path[MAX_PATH]; const DWORD module_result = GetModuleFileNameW(NULL, program_path, arraysize(program_path)); if ((module_result >= arraysize(program_path)) || (module_result == 0)) { // String truncation or some other error. fprintf(stderr, "Cannot get executable path: %s\n", android::base::SystemErrorCodeToString(GetLastError()).c_str()); return -1; } WCHAR args[64]; snwprintf(args, arraysize(args), L"adb -L %s fork-server server --reply-fd %d", socket_spec.c_str(), ack_write_as_int); PROCESS_INFORMATION pinfo; ZeroMemory(&pinfo, sizeof(pinfo)); if (!CreateProcessW( program_path, /* program path */ args, /* the fork-server argument will set the debug = 2 in the child */ NULL, /* process handle is not inheritable */ NULL, /* thread handle is not inheritable */ TRUE, /* yes, inherit some handles */ DETACHED_PROCESS, /* the new process doesn't have a console */ NULL, /* use parent's environment block */ NULL, /* use parent's starting directory */ &startup, /* startup info, i.e. std handles */ &pinfo )) { fprintf(stderr, "Cannot create process: %s\n", android::base::SystemErrorCodeToString(GetLastError()).c_str()); return -1; } unique_handle process_handle(pinfo.hProcess); pinfo.hProcess = NULL; // Close handles that we no longer need to complete the rest. CloseHandle(pinfo.hThread); pinfo.hThread = NULL; nul_read.reset(); ack_write.reset(); stdout_write.reset(); stderr_write.reset(); // Start threads to read from subprocess stdout/stderr and write to ours to make subprocess // errors easier to diagnose. Note that the threads internally create inheritable handles, but // that is ok because we've already spawned the subprocess. // In the past, reading from a pipe before the child process's C Runtime // started up and called GetFileType() caused a hang: http://blogs.msdn.com/b/oldnewthing/archive/2011/12/02/10243553.aspx#10244216 // This is reportedly fixed in Windows Vista: https://support.microsoft.com/en-us/kb/2009703 // I was unable to reproduce the problem on Windows XP. It sounds like a // Windows Update may have fixed this: https://www.duckware.com/tech/peeknamedpipe.html unique_handle stdout_thread(reinterpret_cast<HANDLE>( _beginthreadex(NULL, 0, _redirect_stdout_thread, stdout_read.get(), 0, NULL))); if (stdout_thread.get() == nullptr) { fprintf(stderr, "Cannot create thread: %s\n", strerror(errno)); return -1; } stdout_read.release(); // Transfer ownership to new thread unique_handle stderr_thread(reinterpret_cast<HANDLE>( _beginthreadex(NULL, 0, _redirect_stderr_thread, stderr_read.get(), 0, NULL))); if (stderr_thread.get() == nullptr) { fprintf(stderr, "Cannot create thread: %s\n", strerror(errno)); return -1; } stderr_read.release(); // Transfer ownership to new thread bool got_ack = false; // Wait for the "OK\n" message, for the pipe to be closed, or other error. { char temp[3]; DWORD count = 0; if (ReadFile(ack_read.get(), temp, sizeof(temp), &count, NULL)) { const CHAR expected[] = "OK\n"; const DWORD expected_length = arraysize(expected) - 1; if (count == expected_length && memcmp(temp, expected, expected_length) == 0) { got_ack = true; } else { fprintf(stderr, "ADB server didn't ACK\n"); } } else { const DWORD err = GetLastError(); // If the ACK was not written and the process exited, GetLastError() // is probably ERROR_BROKEN_PIPE, in which case that info is not // useful to the user. fprintf(stderr, "could not read ok from ADB Server%s\n", err == ERROR_BROKEN_PIPE ? "" : android::base::StringPrintf(": %s", android::base::SystemErrorCodeToString(err).c_str()).c_str()); } } // Always try to wait a bit for threads reading stdout/stderr to finish. // If the process started ok, it should close the pipes causing the threads // to finish. If the process had an error, it should exit, also causing // the pipes to be closed. In that case we want to read all of the output // and write it out so that the user can diagnose failures. const DWORD thread_timeout_ms = 15 * 1000; const HANDLE threads[] = { stdout_thread.get(), stderr_thread.get() }; const DWORD wait_result = WaitForMultipleObjects(arraysize(threads), threads, TRUE, thread_timeout_ms); if (wait_result == WAIT_TIMEOUT) { // Threads did not finish after waiting a little while. Perhaps the // server didn't close pipes, or it is hung. fprintf(stderr, "Timed-out waiting for threads to finish reading from " "ADB Server\n"); // Process handles are signaled when the process exits, so if we wait // on the handle for 0 seconds and it returns 'timeout', that means that // the process is still running. if (WaitForSingleObject(process_handle.get(), 0) == WAIT_TIMEOUT) { // We could TerminateProcess(), but that seems somewhat presumptive. fprintf(stderr, "ADB Server is running: process id %lu\n", pinfo.dwProcessId); } return -1; } if (wait_result != WAIT_OBJECT_0) { fprintf(stderr, "Unexpected result waiting for threads: %lu: %s\n", wait_result, android::base::SystemErrorCodeToString(GetLastError()).c_str()); return -1; } // For now ignore the thread exit codes and assume they worked properly. if (!got_ack) { return -1; } #else /* !defined(_WIN32) */ // set up a pipe so the child can tell us when it is ready. // fd[0] will be parent's end, and the child will write on fd[1] int fd[2]; if (pipe(fd)) { fprintf(stderr, "pipe failed in launch_server, errno: %d\n", errno); return -1; } std::string path = android::base::GetExecutablePath(); pid_t pid = fork(); if (pid < 0) return -1; if (pid == 0) { // child side of the fork adb_close(fd[0]); char reply_fd[30]; snprintf(reply_fd, sizeof(reply_fd), "%d", fd[1]); // child process int result = execl(path.c_str(), "adb", "-L", socket_spec.c_str(), "fork-server", "server", "--reply-fd", reply_fd, NULL); // this should not return fprintf(stderr, "OOPS! execl returned %d, errno: %d\n", result, errno); } else { // parent side of the fork char temp[3]; temp[0] = 'A'; temp[1] = 'B'; temp[2] = 'C'; // wait for the "OK\n" message adb_close(fd[1]); int ret = adb_read(fd[0], temp, 3); int saved_errno = errno; adb_close(fd[0]); if (ret < 0) { fprintf(stderr, "could not read ok from ADB Server, errno = %d\n", saved_errno); return -1; } if (ret != 3 || temp[0] != 'O' || temp[1] != 'K' || temp[2] != '\n') { fprintf(stderr, "ADB server didn't ACK\n" ); return -1; } } #endif /* !defined(_WIN32) */ return 0; }
int ScanFilesEx ( CTEXTSTR base , CTEXTSTR mask , void **pInfo , void CPROC Process( uintptr_t psvUser, CTEXTSTR name, int flags ) , int flags , uintptr_t psvUser , LOGICAL begin_sub_path , struct file_system_mounted_interface *mount ) { PMFD pDataCurrent = (PMFD)(pInfo); PMFD pData = (PMFD)(*pInfo); TEXTSTR tmp_base = NULL; int sendflags; int processed = 0; #ifndef WIN32 struct dirent *de; #endif if( begin_sub_path ) { pInfo = (void**)&(pDataCurrent->current); } else pDataCurrent = NULL; //lprintf( "Search in %s for %s %d %d", base?base:"(NULL)", mask?mask:"(*)", (*pInfo)?((PMFD)*pInfo)->scanning_mount:0, (*pInfo)?((PMFD)*pInfo)->single_mount:0 ); if( !*pInfo || begin_sub_path || ((PMFD)*pInfo)->new_mount ) { TEXTCHAR findmask[256]; pData = (PMFD)(*pInfo); if( !pData ) { *pInfo = Allocate( sizeof( MFD ) ); pData = (PMFD)(*pInfo); if( !( pData->scanning_mount = mount ) ) { if( !winfile_local ) SimpleRegisterAndCreateGlobal( winfile_local ); //lprintf( "... %p", winfile_local ); pData->single_mount = FALSE; pData->scanning_mount = (*winfile_local).mounted_file_systems; } else pData->single_mount = TRUE; if( !pData->scanning_mount ) { Deallocate( PMFD, pData ); if( tmp_base ) Release( tmp_base ); return 0; } if( pData->scanning_mount->fsi ) { //lprintf( "create cursor" ); tmp_base = ExpandPathEx( base, pData->scanning_mount->fsi ); pData->cursor = pData->scanning_mount->fsi->find_create_cursor( pData->scanning_mount->psvInstance, CStrDup( tmp_base ), CStrDup( mask ) ); } else { //lprintf( "no cursor" ); pData->cursor = NULL; } } else { if( pData->new_mount ) { if( pData->scanning_mount->fsi ) { //lprintf( "create cursor (new mount)" ); tmp_base = ExpandPathEx( base, pData->scanning_mount->fsi ); pData->cursor = pData->scanning_mount->fsi->find_create_cursor( pData->scanning_mount->psvInstance, CStrDup( tmp_base ), CStrDup( mask ) ); } else pData->cursor = NULL; } } pData->new_mount = FALSE; pData->current = NULL; pData->prior = pDataCurrent; if( pDataCurrent ) { pData->root_info = pDataCurrent->root_info; pInfo = (void**)pData->root_info; } else { pData->root_info = (struct myfinddata**)pInfo; } (*pData->root_info) = pData; if( base ) { TEXTSTR tmp; StrCpyEx( findbasename(pInfo), tmp = ExpandPathEx( base, pData->scanning_mount?pData->scanning_mount->fsi:NULL ), MAX_PATH_NAME ); Release( tmp ); StrCpyEx( findmask(pInfo), mask, MAX_PATH_NAME ); } else { CTEXTSTR p = pathrchr( mask ); if( p ) { StrCpyEx( findbasename(pInfo), mask, p - mask + 1 ); StrCpyEx( findmask(pInfo), p + 1, MAX_PATH_NAME ); //mask = p + 1; } else { StrCpyEx( findbasename(pInfo), WIDE(""), 2 ); StrCpyEx( findmask(pInfo), mask, MAX_PATH_NAME ); } } if( findbasename(pInfo)[0] ) tnprintf( findmask, sizeof(findmask), WIDE("%s/*"), findbasename(pInfo) ); else tnprintf( findmask, sizeof( findmask ), WIDE( "*" ) ); if( pData->scanning_mount?pData->scanning_mount->fsi:NULL ) if( pData->scanning_mount->fsi->find_first( findcursor(pInfo) ) ) findhandle(pInfo) = 0; else findhandle(pInfo) = (HANDLECAST)-1; else { #if WIN32 findhandle(pInfo) = findfirst( findmask, finddata(pInfo) ); #else //lprintf( "opendir %s", findbasename(pInfo) ); findhandle( pInfo ) = opendir( findbasename(pInfo) ); if( !findhandle(pInfo ) ) findhandle(pInfo) = (HANDLECAST)-1; else de = readdir( (DIR*)findhandle( pInfo ) ); #endif } if( findhandle(pInfo) == (HANDLECAST)-1 ) { PMFD prior = pData->prior; //lprintf( "first use of cursor or first open of directoy failed..." ); if( pData->scanning_mount && pData->scanning_mount->fsi ) pData->scanning_mount->fsi->find_close( (struct find_cursor*)findcursor(pInfo) ); else { #ifdef WIN32 findclose( findhandle(pInfo) ); #else // but it failed... so ... don't close //closedir( findhandle( pInfo ) ); #endif } pData->scanning_mount = NextThing( pData->scanning_mount ); if( !pData->scanning_mount || pData->single_mount ) { (*pData->root_info) = pData->prior; if( !begin_sub_path ) { Release( pData ); pInfo[0] = NULL; } //lprintf( WIDE( "%p %d" ), prior, processed ); if( tmp_base ) Release( tmp_base ); return prior?processed:0; } pData->new_mount = TRUE; if( tmp_base ) Release( tmp_base ); return 1; } } else { int r; getnext: //lprintf( "returning customer..." ); if( pData->scanning_mount?pData->scanning_mount->fsi:NULL ) r = !pData->scanning_mount->fsi->find_next( findcursor( pInfo ) ); else { #ifdef _WIN32 r = findnext( findhandle(pInfo), finddata( pInfo ) ); #else de = readdir( (DIR*)findhandle( pInfo ) ); //lprintf( "using %p got %p", findhandle( pInfo ), de ); r = (de == NULL); #endif } if( r ) { PMFD prior = pData->prior; //lprintf( "nothing left to find..." ); if( pData->scanning_mount->fsi ) pData->scanning_mount->fsi->find_close( findcursor(pInfo) ); else { #ifdef WIN32 findclose( findhandle(pInfo) ); #else closedir( (DIR*)findhandle(pInfo)); #endif } pData->scanning_mount = NextThing( pData->scanning_mount ); //lprintf( "Step mount... %p %d", pData->scanning_mount, pData->single_mount ); if( !pData->scanning_mount || pData->single_mount ) { //lprintf( "done with mounts?" ); (*pData->root_info) = pData->prior; Release( pData ); if( prior ) prior->current = NULL; if( !processed && !begin_sub_path ) { //pInfo = (void**)&(prior->prior->current); pData = prior; if( pData ) goto getnext; } if( tmp_base ) Release( tmp_base ); return (*pInfo)?processed:0; } pData->new_mount = TRUE; if( tmp_base ) Release( tmp_base ); return 1; } } if( pData->scanning_mount?pData->scanning_mount->fsi:NULL ) { char * path = pData->scanning_mount->fsi->find_get_name( findcursor(pInfo) ); //lprintf( "... %s", path ); if( !strcmp( ".", path ) || !strcmp( "..", path ) ) goto getnext; } else { #if WIN32 //lprintf( "... %s", finddata(pInfo)->name ); # ifdef UNDER_CE if( !StrCmp( WIDE("."), finddata(pInfo)->cFileName ) || !StrCmp( WIDE(".."), finddata(pInfo)->cFileName ) ) # else if( !StrCmp( WIDE("."), finddata(pInfo)->name ) || !StrCmp( WIDE(".."), finddata(pInfo)->name ) ) # endif #else if( !StrCmp( WIDE("."), de->d_name ) || !StrCmp( WIDE(".."), de->d_name ) ) #endif goto getnext; } if( !(flags & SFF_NAMEONLY) ) // if nameonly - have to rebuild the correct name. { if( pData->scanning_mount?pData->scanning_mount->fsi:NULL ) { tnprintf( pData->file_buffer, MAX_PATH_NAME, WIDE("%s"), pData->scanning_mount->fsi->find_get_name( findcursor(pInfo) ) ); if( findbasename( pInfo )[0] ) tnprintf( pData->buffer, MAX_PATH_NAME, WIDE("%s/%s"), findbasename(pInfo), pData->file_buffer ); else tnprintf( pData->buffer, MAX_PATH_NAME, WIDE( "%s" ), pData->file_buffer ); } else { #ifdef WIN32 # ifdef UNDER_CE tnprintf( pData->file_buffer, MAX_PATH_NAME, WIDE( "%s" ), finddata( pInfo )->cFileName ); tnprintf( pData->buffer, MAX_PATH_NAME, WIDE("%s/%s"), findbasename(pInfo), finddata(pInfo)->cFileName ); # else tnprintf( pData->file_buffer, MAX_PATH_NAME, WIDE("%s"), finddata(pInfo)->name ); tnprintf( pData->buffer, MAX_PATH_NAME, WIDE("%s%s%s"), findbasename(pInfo), findbasename( pInfo )[0]?"/":"", pData->file_buffer ); # endif #else tnprintf( pData->file_buffer, MAX_PATH_NAME, WIDE("%s"), de->d_name ); tnprintf( pData->buffer, MAX_PATH_NAME, WIDE("%s/%s"), findbasename(pInfo), de->d_name ); #endif } } else { if( flags & SFF_SUBCURSE ) { if( pData->scanning_mount?pData->scanning_mount->fsi:NULL ) { tnprintf( pData->buffer, MAX_PATH_NAME, WIDE("%s%s%s") , pData->prior?pData->prior->buffer:WIDE( "" ) , pData->prior?WIDE( "/" ):WIDE( "" ) , pData->scanning_mount->fsi->find_get_name( findcursor(pInfo) ) ); } else { #if WIN32 # ifdef UNDER_CE tnprintf( pData->buffer, MAX_PATH_NAME, WIDE("%s%s%s") , pData->prior?pData->prior->buffer:WIDE( "" ) , pData->prior?WIDE( "/" ):WIDE( "" ) , finddata(pInfo)->cFileName ); # else tnprintf( pData->buffer, MAX_PATH_NAME, WIDE("%s%s%s") , pData->prior?pData->prior->buffer:WIDE( "" ) , pData->prior?WIDE( "/" ):WIDE( "" ) , finddata(pInfo)->name ); # endif #else tnprintf( pData->buffer, MAX_PATH_NAME, WIDE("%s%s%s") , pData->prior?pData->prior->buffer:WIDE( "" ) , pData->prior?WIDE( "/" ):WIDE( "" ) , de->d_name ); lprintf( "resulting is %s", pData->buffer ); #endif } } else { if( pData->scanning_mount?pData->scanning_mount->fsi:NULL ) { tnprintf( pData->buffer, MAX_PATH_NAME, WIDE("%s"), pData->scanning_mount->fsi->find_get_name( findcursor(pInfo) ) ); } else { #if WIN32 # ifdef UNDER_CE tnprintf( pData->buffer, MAX_PATH_NAME, WIDE("%s"), finddata(pInfo)->cFileName ); # else # ifdef UNICODE snwprintf( pData->buffer, MAX_PATH_NAME, WIDE("%s"), finddata(pInfo)->name ); # else tnprintf( pData->buffer, MAX_PATH_NAME, WIDE("%s"), finddata(pInfo)->name ); # endif # endif #else tnprintf( pData->buffer, MAX_PATH_NAME, WIDE("%s"), de->d_name ); #endif } } } pData->buffer[MAX_PATH_NAME-1] = 0; // force nul termination... #ifdef UNICODE { char *pDataBuffer = CStrDup( pData->buffer ); #else # define pDataBuffer pData->buffer #endif //lprintf( "Check if %s is a directory...", pData->buffer ); if( (flags & (SFF_DIRECTORIES | SFF_SUBCURSE)) && (pData->scanning_mount && pData->scanning_mount->fsi && (pData->scanning_mount->fsi->is_directory && pData->scanning_mount->fsi->is_directory( pDataBuffer ))) || (!(pData->scanning_mount ? pData->scanning_mount->fsi : NULL) #ifdef WIN32 # ifdef UNDER_CE && (finddata( pInfo )->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) # else && (finddata( pInfo )->attrib & _A_SUBDIR) # endif #else && IsPath( pData->buffer ) #endif ) ) { #ifdef UNICODE Deallocate( char *, pDataBuffer ); #else # undef pDataBuffer #endif //lprintf( "... it is?" ); if( flags & SFF_DIRECTORIES ) { if( Process != NULL ) { //lprintf( "Send %s", pData->buffer ); Process( psvUser, pData->buffer, SFF_DIRECTORY ); processed = 1; } //return 1; } if( flags & SFF_SUBCURSE ) { void *data = NULL; int ofs = 0; TEXTCHAR tmpbuf[MAX_PATH_NAME]; if( flags & SFF_NAMEONLY ) { // even in name only - need to have this full buffer for subcurse. if( pData->scanning_mount && pData->scanning_mount->fsi ) { ofs = tnprintf( tmpbuf, sizeof( tmpbuf ), WIDE( "%s/%s" ), findbasename( pInfo ), pData->scanning_mount->fsi->find_get_name( findcursor( pInfo ) ) ); } else { #ifdef WIN32 # ifdef UNDER_CE ofs = tnprintf( tmpbuf, sizeof( tmpbuf ), WIDE( "%s/%s" ), findbasename( pInfo ), finddata( pInfo )->cFileName ); # else # ifdef UNICODE ofs = snwprintf( tmpbuf, sizeof( tmpbuf ), WIDE( "%s/%s" ), findbasename( pInfo ), finddata( pInfo )->name ); # else ofs = tnprintf( tmpbuf, sizeof( tmpbuf ), WIDE( "%s/%s" ), findbasename( pInfo ), finddata( pInfo )->name ); # endif # endif #else ofs = tnprintf( tmpbuf, sizeof( tmpbuf ), WIDE( "%s/%s" ), findbasename( pInfo ), de->d_name ); #endif } //lprintf( "process sub... %s %s", tmpbuf, findmask(pInfo) ); processed |= ScanFilesEx( tmpbuf, findmask( pInfo ), (POINTER*)pData, Process, flags, psvUser, TRUE, pData->scanning_mount ); } else { //lprintf( "process sub..." ); processed |= ScanFilesEx( pData->buffer, findmask( pInfo ), (POINTER*)pData, Process, flags, psvUser, TRUE, pData->scanning_mount ); } } if( !processed ) goto getnext; if( tmp_base ) Release( tmp_base ); return (*pInfo) ? 1 : 0; } #ifdef UNICODE Deallocate( char *, pDataBuffer ); } #else # undef pDataBuffer #endif if( ( sendflags = SFF_DIRECTORY, ( ( flags & SFF_DIRECTORIES ) #ifdef WIN32 # ifdef UNDER_CE && ( finddata(pInfo)->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ) # else && ( finddata(pInfo)->attrib & _A_SUBDIR ) # endif #else && ( IsPath( pData->buffer ) ) #endif ) ) || ( sendflags = 0, CompareMask( findmask( pInfo ) #ifdef WIN32 # ifdef UNDER_CE , finddata(pInfo)->cFileName # else , pData->file_buffer # endif #else , de->d_name #endif // yes this is silly - but it's correct... , (flags & SFF_IGNORECASE)?0:0 ) ) ) { //lprintf( "Send %s", pData->buffer ); if( Process != NULL ) Process( psvUser, pData->buffer, sendflags ); if( tmp_base ) Release( tmp_base ); return (*pInfo)?1:0; } if( tmp_base ) Release( tmp_base ); return (*pInfo)?1:0; }
int launch_server(int server_port) { #if defined(_WIN32) /* we need to start the server in the background */ /* we create a PIPE that will be used to wait for the server's "OK" */ /* message since the pipe handles must be inheritable, we use a */ /* security attribute */ HANDLE nul_read, nul_write; HANDLE pipe_read, pipe_write; HANDLE stdout_handle, stderr_handle; SECURITY_ATTRIBUTES sa; STARTUPINFOW startup; PROCESS_INFORMATION pinfo; WCHAR program_path[ MAX_PATH ]; int ret; sa.nLength = sizeof(sa); sa.lpSecurityDescriptor = NULL; sa.bInheritHandle = TRUE; /* Redirect stdin and stderr to Windows /dev/null. If we instead pass our * stdin/stderr handles and they are console handles, when the adb server * starts up, the C Runtime will see console handles for a process that * isn't connected to a console and it will configure stderr to be closed. * At that point, freopen() could be used to reopen stderr, but it would * take more massaging to fixup the file descriptor number that freopen() * uses. It's simplest to avoid all of this complexity by just redirecting * stdin/stderr to `nul' and then the C Runtime acts as expected. */ nul_read = CreateFileW(L"nul", GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, &sa, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (nul_read == INVALID_HANDLE_VALUE) { fprintf(stderr, "CreateFileW(nul, GENERIC_READ) failed: %s\n", SystemErrorCodeToString(GetLastError()).c_str()); return -1; } nul_write = CreateFileW(L"nul", GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, &sa, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (nul_write == INVALID_HANDLE_VALUE) { fprintf(stderr, "CreateFileW(nul, GENERIC_WRITE) failed: %s\n", SystemErrorCodeToString(GetLastError()).c_str()); CloseHandle(nul_read); return -1; } /* create pipe, and ensure its read handle isn't inheritable */ ret = CreatePipe( &pipe_read, &pipe_write, &sa, 0 ); if (!ret) { fprintf(stderr, "CreatePipe() failed: %s\n", SystemErrorCodeToString(GetLastError()).c_str()); CloseHandle(nul_read); CloseHandle(nul_write); return -1; } SetHandleInformation( pipe_read, HANDLE_FLAG_INHERIT, 0 ); /* Some programs want to launch an adb command and collect its output by * calling CreateProcess with inheritable stdout/stderr handles, then * using read() to get its output. When this happens, the stdout/stderr * handles passed to the adb client process will also be inheritable. * When starting the adb server here, care must be taken to reset them * to non-inheritable. * Otherwise, something bad happens: even if the adb command completes, * the calling process is stuck while read()-ing from the stdout/stderr * descriptors, because they're connected to corresponding handles in the * adb server process (even if the latter never uses/writes to them). */ stdout_handle = GetStdHandle( STD_OUTPUT_HANDLE ); stderr_handle = GetStdHandle( STD_ERROR_HANDLE ); if (stdout_handle != INVALID_HANDLE_VALUE) { SetHandleInformation( stdout_handle, HANDLE_FLAG_INHERIT, 0 ); } if (stderr_handle != INVALID_HANDLE_VALUE) { SetHandleInformation( stderr_handle, HANDLE_FLAG_INHERIT, 0 ); } ZeroMemory( &startup, sizeof(startup) ); startup.cb = sizeof(startup); startup.hStdInput = nul_read; startup.hStdOutput = pipe_write; startup.hStdError = nul_write; startup.dwFlags = STARTF_USESTDHANDLES; ZeroMemory( &pinfo, sizeof(pinfo) ); /* get path of current program */ DWORD module_result = GetModuleFileNameW(NULL, program_path, arraysize(program_path)); if ((module_result == arraysize(program_path)) || (module_result == 0)) { // String truncation or some other error. fprintf(stderr, "GetModuleFileNameW() failed: %s\n", SystemErrorCodeToString(GetLastError()).c_str()); return -1; } WCHAR args[64]; snwprintf(args, arraysize(args), L"adb -P %d fork-server server", server_port); ret = CreateProcessW( program_path, /* program path */ args, /* the fork-server argument will set the debug = 2 in the child */ NULL, /* process handle is not inheritable */ NULL, /* thread handle is not inheritable */ TRUE, /* yes, inherit some handles */ DETACHED_PROCESS, /* the new process doesn't have a console */ NULL, /* use parent's environment block */ NULL, /* use parent's starting directory */ &startup, /* startup info, i.e. std handles */ &pinfo ); CloseHandle( nul_read ); CloseHandle( nul_write ); CloseHandle( pipe_write ); if (!ret) { fprintf(stderr, "CreateProcess failed: %s\n", SystemErrorCodeToString(GetLastError()).c_str()); CloseHandle( pipe_read ); return -1; } CloseHandle( pinfo.hProcess ); CloseHandle( pinfo.hThread ); /* wait for the "OK\n" message */ { char temp[3]; DWORD count; ret = ReadFile( pipe_read, temp, 3, &count, NULL ); CloseHandle( pipe_read ); if ( !ret ) { fprintf(stderr, "could not read ok from ADB Server, error: %s\n", SystemErrorCodeToString(GetLastError()).c_str()); return -1; } if (count != 3 || temp[0] != 'O' || temp[1] != 'K' || temp[2] != '\n') { fprintf(stderr, "ADB server didn't ACK\n" ); return -1; } } #else /* !defined(_WIN32) */ char path[PATH_MAX]; int fd[2]; // set up a pipe so the child can tell us when it is ready. // fd[0] will be parent's end, and the child will write on fd[1] if (pipe(fd)) { fprintf(stderr, "pipe failed in launch_server, errno: %d\n", errno); return -1; } get_my_path(path, PATH_MAX); pid_t pid = fork(); if(pid < 0) return -1; if (pid == 0) { // child side of the fork adb_close(fd[0]); char str_port[30]; snprintf(str_port, sizeof(str_port), "%d", server_port); char reply_fd[30]; snprintf(reply_fd, sizeof(reply_fd), "%d", fd[1]); // child process int result = execl(path, "adb", "-P", str_port, "fork-server", "server", "--reply-fd", reply_fd, NULL); // this should not return fprintf(stderr, "OOPS! execl returned %d, errno: %d\n", result, errno); } else { // parent side of the fork char temp[3]; temp[0] = 'A'; temp[1] = 'B'; temp[2] = 'C'; // wait for the "OK\n" message adb_close(fd[1]); int ret = adb_read(fd[0], temp, 3); int saved_errno = errno; adb_close(fd[0]); if (ret < 0) { fprintf(stderr, "could not read ok from ADB Server, errno = %d\n", saved_errno); return -1; } if (ret != 3 || temp[0] != 'O' || temp[1] != 'K' || temp[2] != '\n') { fprintf(stderr, "ADB server didn't ACK\n" ); return -1; } setsid(); } #endif /* !defined(_WIN32) */ return 0; }
int convert_h3c(const wchar_t *src_path, const wchar_t *filename, const wchar_t *dest_path, convert_cb_t cb, void *cb_data) { h3clib_ctx_t h3c = NULL; wchar_t fullpath[MAX_PATH] = { 0 }; wchar_t fullpath_out[MAX_PATH] = { 0 }; const wchar_t *version_src = L"unknown"; const wchar_t *version_dst = L"unknown"; enum H3M_FORMAT fm_src = 0; int ret = 0; int result = 0; snwprintf(fullpath, sizeof(fullpath) / sizeof(fullpath[0])-1, L"%s\\%s", src_path, filename); h3c_read_convert_u(&h3c, fullpath, 0, &fm_src, NULL, NULL); // Error check, if h3c is NULL then conversion failed if (NULL == h3c) { if (NULL != cb) { switch (fm_src) { case H3C_FORMAT_SOD: case H3C_FORMAT_CHR: result = CONVERT_RESULT_FAIL; break; default: CONVERT_RESULT_SKIP; break; } if (0 != (ret = cb(filename, fm_src, result, cb_data))) { return ret; } } return 0; } switch (fm_src) { case H3C_FORMAT_SOD: version_src = L"SoD"; version_dst = L"CHR"; break; case H3C_FORMAT_CHR: version_src = L"CHR"; version_dst = L"SoD"; break; default: break; } snwprintf(fullpath_out, sizeof(fullpath_out) / sizeof(fullpath_out[0]) - 1, L"%s\\[%s-%s] %s", dest_path, version_src, version_dst, filename); h3c_write_u(h3c, fullpath_out); //h3m_compress(fullpath_out, fullpath_out); h3c_exit(&h3c); if (NULL != cb) { if (0 != (ret = cb(filename, fm_src, CONVERT_RESULT_SUCCESS, cb_data))) { return ret; } } return 0; }
/* * Validate options against a white list. Also check the config_file is * inside the config_dir. The white list is defined in validate.c * Returns true on success */ static BOOL ValidateOptions (HANDLE pipe, const WCHAR *workdir, const WCHAR *options) { WCHAR **argv; int argc; WCHAR buf[256]; BOOL ret = FALSE; int i; const WCHAR *msg1 = L"You have specified a config file location (%s relative to %s)" " that requires admin approval. This error may be avoided" " by adding your account to the \"%s\" group"; const WCHAR *msg2 = L"You have specified an option (%s) that may be used" " only with admin approval. This error may be avoided" " by adding your account to the \"%s\" group"; argv = CommandLineToArgvW (options, &argc); if (!argv) { ReturnLastError (pipe, L"CommandLineToArgvW"); ReturnError (pipe, ERROR_STARTUP_DATA, L"Cannot validate options", 1, &exit_event); goto out; } /* Note: argv[0] is the first option */ if (argc < 1) /* no options */ { ret = TRUE; goto out; } /* * If only one argument, it is the config file */ if (argc == 1) { WCHAR *argv_tmp[2] = { L"--config", argv[0] }; if (!CheckOption (workdir, 2, argv_tmp, &settings)) { snwprintf (buf, _countof(buf), msg1, argv[0], workdir, settings.ovpn_admin_group); buf[_countof(buf) - 1] = L'\0'; ReturnError (pipe, ERROR_STARTUP_DATA, buf, 1, &exit_event); } goto out; } for (i = 0; i < argc; ++i) { if (!IsOption(argv[i])) continue; if (!CheckOption (workdir, argc-i, &argv[i], &settings)) { if (wcscmp(L"--config", argv[i]) == 0 && argc-i > 1) { snwprintf (buf, _countof(buf), msg1, argv[i+1], workdir, settings.ovpn_admin_group); buf[_countof(buf) - 1] = L'\0'; ReturnError (pipe, ERROR_STARTUP_DATA, buf, 1, &exit_event); } else { snwprintf (buf, _countof(buf), msg2, argv[i], settings.ovpn_admin_group); buf[_countof(buf) - 1] = L'\0'; ReturnError (pipe, ERROR_STARTUP_DATA, buf, 1, &exit_event); } goto out; } } /* all options passed */ ret = TRUE; out: if (argv) LocalFree (argv); return ret; }
void plCreateMenu() { #if MAX_VERSION_MAJOR <= 11 AddPlasmaExportMenu(); #endif IMenuManager* pMenuMan = GetCOREInterface()->GetMenuManager(); bool newlyRegistered = pMenuMan->RegisterMenuBarContext(kMyMenuContextId, kMenuName); // Is the Max menu version the most recent? bool wrongVersion = GetPrivateProfileIntW(L"Menu", L"Version", 0, plMaxConfig::GetPluginIni().WideString().data()) < kMenuVersion; if (wrongVersion) { // Delete the old version of the menu IMenu *oldMenu = pMenuMan->FindMenu(kMenuName); if (oldMenu) pMenuMan->UnRegisterMenu(oldMenu); // Update the menu version wchar_t buf[12]; snwprintf(buf, arrsize(buf), L"%d", kMenuVersion); WritePrivateProfileStringW(L"Menu", L"Version", buf, plMaxConfig::GetPluginIni().WideString().data()); } if (wrongVersion || newlyRegistered) { IMenu *pMainMenu = pMenuMan->GetMainMenuBar(); if (!pMainMenu) { hsAssert(0, "Main menu not found"); return; } // Get our action table ActionTable* pActionTable = GetCOREInterface()->GetActionManager()->FindTable(kActionId); if (!pActionTable) { hsAssert(0, "Action table not found"); return; } // Create the Plasma menu IMenu* pPlasmaMenu = GetIMenu(); pPlasmaMenu->SetTitle(kMenuName); // Register the new menu with the system pMenuMan->RegisterMenu(pPlasmaMenu, 0); ///////////////////////////////////////////////// // Add the menu items // IMenuItem* pMenuItem; #if MAX_VERSION_MAJOR >= 12 // Add the export action to the menu pMenuItem = GetIMenuItem(); pMenuItem->SetActionItem(pActionTable->GetAction(kActionExport)); pPlasmaMenu->AddItem(pMenuItem); #endif // Add the save selected action to the menu pMenuItem = GetIMenuItem(); pMenuItem->SetActionItem(pActionTable->GetAction(kActionSaveSel)); pPlasmaMenu->AddItem(pMenuItem); // Add the merge action to the menu pMenuItem = GetIMenuItem(); pMenuItem->SetActionItem(pActionTable->GetAction(kActionMerge)); pPlasmaMenu->AddItem(pMenuItem); // Add the component copy action to the menu pMenuItem = GetIMenuItem(); pMenuItem->SetActionItem(pActionTable->GetAction(kActionCompCopy)); pPlasmaMenu->AddItem(pMenuItem); // Add a separator pMenuItem = GetIMenuItem(); pMenuItem->ActAsSeparator(); pPlasmaMenu->AddItem(pMenuItem); // Add the component manager to the menu pMenuItem = GetIMenuItem(); pMenuItem->SetActionItem(pActionTable->GetAction(kActionComponent)); pPlasmaMenu->AddItem(pMenuItem); // Add the resource collector to the menu pMenuItem = GetIMenuItem(); pMenuItem->SetActionItem(pActionTable->GetAction(kActionResCollect)); pPlasmaMenu->AddItem(pMenuItem); // Add the texture search to the menu pMenuItem = GetIMenuItem(); pMenuItem->SetActionItem(pActionTable->GetAction(kActionTexSearch)); pPlasmaMenu->AddItem(pMenuItem); // Add the age description to the menu pMenuItem = GetIMenuItem(); pMenuItem->SetActionItem(pActionTable->GetAction(kActionAgeDesc)); pPlasmaMenu->AddItem(pMenuItem); // Add a separator pMenuItem = GetIMenuItem(); pMenuItem->ActAsSeparator(); pPlasmaMenu->AddItem(pMenuItem); // Add the Lock Selected to the menu pMenuItem = GetIMenuItem(); pMenuItem->SetActionItem(pActionTable->GetAction(kActionLock)); pPlasmaMenu->AddItem(pMenuItem); // Add the Unlock Selected to the menu pMenuItem = GetIMenuItem(); pMenuItem->SetActionItem(pActionTable->GetAction(kActionUnlock)); pPlasmaMenu->AddItem(pMenuItem); // Add the Reset Selected to the menu pMenuItem = GetIMenuItem(); pMenuItem->SetActionItem(pActionTable->GetAction(kActionReset)); pPlasmaMenu->AddItem(pMenuItem); // Add the SelectNonRenderables to the menu pMenuItem = GetIMenuItem(); pMenuItem->SetActionItem(pActionTable->GetAction(kActionSelectNonRenderables)); pPlasmaMenu->AddItem(pMenuItem); // Create a new menu item to hold the sub-menu IMenuItem* pSubMenuItem1 = GetIMenuItem(); //menu in menu bar... pSubMenuItem1->SetSubMenu(pPlasmaMenu); pMainMenu->AddItem(pSubMenuItem1); pMenuMan->UpdateMenuBar(); // Save the dang menu, in case Max crashes const char *uiDir = GetCOREInterface()->GetDir(APP_UI_DIR); char path[MAX_PATH]; sprintf(path, "%s\\%s", uiDir, "MaxMenus.mnu"); pMenuMan->SaveMenuFile(path); } }
int ISO8601::ToString(const struct tm& value, wchar_t *wstr, int *wlen) { //2010-06-08T14:26:23Z *wlen = snwprintf(wstr, *wlen, L"%.4d-%.2d-%.2dT%.2d:%.2d:%.2dZ", (1900 + value.tm_year), (1 + value.tm_mon), value.tm_mday, value.tm_hour, value.tm_min, value.tm_sec); return (errno = 0); }