ResultType Clipboard::Set(LPCTSTR aBuf, UINT_PTR aLength) // Returns OK or FAIL. { // It was already open for writing from a prior call. Return failure because callers that do this // are probably handling things wrong: if (IsReadyForWrite()) return FAIL; if (!aBuf) { aBuf = _T(""); aLength = 0; } else if (aLength == UINT_MAX) // Caller wants us to determine the length. aLength = (UINT)_tcslen(aBuf); if (aLength) { if (!PrepareForWrite(aLength + 1)) return FAIL; // It already displayed the error. tcslcpy(mClipMemNewLocked, aBuf, aLength + 1); // Copy only a substring, if aLength specifies such. } // else just do the below to empty the clipboard, which is different than setting // the clipboard equal to the empty string: it's not truly empty then, as reported // by IsClipboardFormatAvailable(CF_TEXT) -- and we want to be able to make it truly // empty for use with functions such as ClipWait: return Commit(); // It will display any errors. }
ResultType Clipboard::Set(LPCTSTR aBuf, UINT_PTR aLength) //, bool aTrimIt) // Returns OK or FAIL. { // It was already open for writing from a prior call. Return failure because callers that do this // are probably handling things wrong: if (IsReadyForWrite()) return FAIL; if (!aBuf) { aBuf = _T(""); aLength = 0; } else if (aLength == UINT_MAX) // Caller wants us to determine the length. aLength = (UINT)_tcslen(aBuf); if (aLength) { if (!PrepareForWrite(aLength + 1)) return FAIL; // It already displayed the error. tcslcpy(mClipMemNewLocked, aBuf, aLength + 1); // Copy only a substring, if aLength specifies such. // Only trim when the caller told us to, rather than always if g_script.mIsAutoIt2 // is true, since AutoIt2 doesn't always trim things (e.g. FileReadLine probably // does not trim the line that was read into its output var). UPDATE: This is // no longer needed because I think AutoIt2 only auto-trims when SetEnv is used: //if (aTrimIt) // trim(mClipMemNewLocked); } // else just do the below to empty the clipboard, which is different than setting // the clipboard equal to the empty string: it's not truly empty then, as reported // by IsClipboardFormatAvailable(CF_TEXT) -- and we want to be able to make it truly // empty for use with functions such as ClipWait: return Commit(); // It will display any errors. }
/// notify log static void notifyLog(_TCHAR *i_msg) { NotifyLog nl; nl.m_type = Notify::Type_log; tcslcpy(nl.m_msg, i_msg, NUMBER_OF(nl.m_msg)); notify(&nl, sizeof(nl)); }
/// notify WM_Targetted static void notifyName(HWND i_hwnd, Notify::Type i_type = Notify::Type_name) { tstringi className; tstring titleName; getClassNameTitleName(i_hwnd, g.m_isInMenu, &className, &titleName); NotifySetFocus *nfc = new NotifySetFocus; nfc->m_type = i_type; nfc->m_threadId = GetCurrentThreadId(); nfc->m_hwnd = reinterpret_cast<DWORD>(i_hwnd); tcslcpy(nfc->m_className, className.c_str(), NUMBER_OF(nfc->m_className)); tcslcpy(nfc->m_titleName, titleName.c_str(), NUMBER_OF(nfc->m_titleName)); notify(nfc, sizeof(*nfc)); delete nfc; }
void callFuncDllVariant(FuncAndToken *aFuncAndToken) { Func &func = *(aFuncAndToken->mFunc); ExprTokenType & aResultToken = aFuncAndToken->mToken ; // Func &func = *(Func *)g_script.mTempFunc ; if (!INTERRUPTIBLE_IN_EMERGENCY) return; if (g_nThreads >= g_MaxThreadsTotal) // Below: Only a subset of ACT_IS_ALWAYS_ALLOWED is done here because: // 1) The omitted action types seem too obscure to grant always-run permission for msg-monitor events. // 2) Reduction in code size. if (g_nThreads >= MAX_THREADS_EMERGENCY // To avoid array overflow, this limit must by obeyed except where otherwise documented. || func.mJumpToLine->mActionType != ACT_EXITAPP && func.mJumpToLine->mActionType != ACT_RELOAD) return; // Need to check if backup is needed in case script explicitly called the function rather than using // it solely as a callback. UPDATE: And now that max_instances is supported, also need it for that. // See ExpandExpression() for detailed comments about the following section. VarBkp *var_backup = NULL; // If needed, it will hold an array of VarBkp objects. int var_backup_count; // The number of items in the above array. if (func.mInstances > 0) // Backup is needed. if (!Var::BackupFunctionVars(func, var_backup, var_backup_count)) // Out of memory. return; // Since we're in the middle of processing messages, and since out-of-memory is so rare, // it seems justifiable not to have any error reporting and instead just avoid launching // the new thread. // Since above didn't return, the launch of the new thread is now considered unavoidable. // See MsgSleep() for comments about the following section. TCHAR ErrorLevel_saved[ERRORLEVEL_SAVED_SIZE]; tcslcpy(ErrorLevel_saved, g_ErrorLevel->Contents(), _countof(ErrorLevel_saved)); InitNewThread(0, false, true, func.mJumpToLine->mActionType); // v1.0.38.04: Below was added to maximize responsiveness to incoming messages. The reasoning // is similar to why the same thing is done in MsgSleep() prior to its launch of a thread, so see // MsgSleep for more comments: g_script.mLastScriptRest = g_script.mLastPeekTime = GetTickCount(); DEBUGGER_STACK_PUSH(func.mJumpToLine, func.mName) // ExprTokenType aResultToken; // ExprTokenType &aResultToken = aResultToken_to_return ; func.Call(&aResultToken); // Call the UDF. TokenToVariant(aResultToken, aFuncAndToken->variant_to_return_dll); DEBUGGER_STACK_POP() ResumeUnderlyingThread(ErrorLevel_saved); return; }
ResultType Line::RegWrite(DWORD aValueType, HKEY aRootKey, LPTSTR aRegSubkey, LPTSTR aValueName, LPTSTR aValue) // If aValueName is the empty string, the key's default value is used. { HKEY hRegKey; DWORD dwRes, dwBuf; // My: Seems safest to keep the limit just below 64K in case Win95 has problems with larger values. TCHAR szRegBuffer[65535], *buf; // Only allow writing of 64Kb to a key for Win9x, which is all it supports. #define SET_REG_BUF \ if (g_os.IsWin9x())\ {\ tcslcpy(szRegBuffer, aValue, sizeof(szRegBuffer));\ buf = szRegBuffer;\ }\ else\ buf = aValue; LONG result; if (!aRootKey || aValueType == REG_NONE || aValueType == REG_SUBKEY) // Can't write to these. { result = ERROR_INVALID_PARAMETER; // Indicate the error. goto finish; } // Open/Create the registry key // The following works even on root keys (i.e. blank subkey), although values can't be created/written to // HKCU's root level, perhaps because it's an alias for a subkey inside HKEY_USERS. Even when RegOpenKeyEx() // is used on HKCU (which is probably redundant since it's a pre-opened key?), the API can't create values // there even though RegEdit can. result = RegCreateKeyEx(aRootKey, aRegSubkey, 0, _T(""), REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hRegKey, &dwRes); if (result != ERROR_SUCCESS) goto finish; // Write the registry differently depending on type of variable we are writing switch (aValueType) { case REG_SZ: SET_REG_BUF result = RegSetValueEx(hRegKey, aValueName, 0, REG_SZ, (CONST BYTE *)buf, (DWORD)(_tcslen(buf)+1) * sizeof(TCHAR)); break; case REG_EXPAND_SZ: SET_REG_BUF result = RegSetValueEx(hRegKey, aValueName, 0, REG_EXPAND_SZ, (CONST BYTE *)buf, (DWORD)(_tcslen(buf)+1) * sizeof(TCHAR)); break; case REG_MULTI_SZ: { // Don't allow values over 64K for this type because aValue might not be a writable // string, and we would need to write to it to temporarily change the newline delimiters // into zero-delimiters. Even if we were to require callers to give us a modifiable string, // its capacity be 1 byte too small to handle the double termination that's needed // (i.e. if the last item in the list happens to not end in a newline): tcslcpy(szRegBuffer, aValue, _countof(szRegBuffer) - 1); // -1 to leave space for a 2nd terminator. // Double-terminate: size_t length = _tcslen(szRegBuffer); szRegBuffer[length + 1] = '\0'; // Remove any final newline the user may have provided since we don't want the length // to include it when calling RegSetValueEx() -- it would be too large by 1: if (length > 0 && szRegBuffer[length - 1] == '\n') szRegBuffer[--length] = '\0'; // Replace the script's delimiter char with the zero-delimiter needed by RegSetValueEx(): for (LPTSTR cp = szRegBuffer; *cp; ++cp) if (*cp == '\n') *cp = '\0'; result = RegSetValueEx(hRegKey, aValueName, 0, REG_MULTI_SZ, (CONST BYTE *)szRegBuffer , (DWORD)(length ? length + 2 : 0) * sizeof(TCHAR)); break; } case REG_DWORD: if (*aValue) dwBuf = ATOU(aValue); // Changed to ATOU() for v1.0.24 so that hex values are supported. else // Default to 0 when blank. dwBuf = 0; result = RegSetValueEx(hRegKey, aValueName, 0, REG_DWORD, (CONST BYTE *)&dwBuf, sizeof(dwBuf)); break; case REG_BINARY: { int nLen = (int)_tcslen(aValue); // String length must be a multiple of 2 if (nLen % 2) { result = ERROR_INVALID_PARAMETER; break; } // Really crappy hex conversion int j = 0, i = 0, nVal, nMult; LPBYTE pRegBuffer = (LPBYTE) szRegBuffer; while (i < nLen && j < sizeof(szRegBuffer)) { nVal = 0; for (nMult = 16; nMult >= 0; nMult = nMult - 15) { if (aValue[i] >= '0' && aValue[i] <= '9') nVal += (aValue[i] - '0') * nMult; else if (aValue[i] >= 'A' && aValue[i] <= 'F') nVal += (((aValue[i] - 'A'))+10) * nMult; else if (aValue[i] >= 'a' && aValue[i] <= 'f') nVal += (((aValue[i] - 'a'))+10) * nMult; else { RegCloseKey(hRegKey); result = ERROR_INVALID_PARAMETER; goto finish; } ++i; } pRegBuffer[j++] = (char)nVal; } result = RegSetValueEx(hRegKey, aValueName, 0, REG_BINARY, pRegBuffer, (DWORD)j); break; } default: result = ERROR_INVALID_PARAMETER; // Anything other than ERROR_SUCCESS. break; } // switch() RegCloseKey(hRegKey); // Additionally, fall through to below: finish: return SetErrorsOrThrow(result != ERROR_SUCCESS, result); } // RegWrite()
//H30 changed to not return anything since it is not used void callFuncDll(FuncAndToken *aFuncAndToken) { Func &func = *(aFuncAndToken->mFunc); ExprTokenType & aResultToken = aFuncAndToken->mToken ; // Func &func = *(Func *)g_script.mTempFunc ; if (!INTERRUPTIBLE_IN_EMERGENCY) return; if (g_nThreads >= g_MaxThreadsTotal) // Below: Only a subset of ACT_IS_ALWAYS_ALLOWED is done here because: // 1) The omitted action types seem too obscure to grant always-run permission for msg-monitor events. // 2) Reduction in code size. if (g_nThreads >= MAX_THREADS_EMERGENCY // To avoid array overflow, this limit must by obeyed except where otherwise documented. || func.mJumpToLine->mActionType != ACT_EXITAPP && func.mJumpToLine->mActionType != ACT_RELOAD) return; // Need to check if backup is needed in case script explicitly called the function rather than using // it solely as a callback. UPDATE: And now that max_instances is supported, also need it for that. // See ExpandExpression() for detailed comments about the following section. VarBkp *var_backup = NULL; // If needed, it will hold an array of VarBkp objects. int var_backup_count; // The number of items in the above array. if (func.mInstances > 0) // Backup is needed. if (!Var::BackupFunctionVars(func, var_backup, var_backup_count)) // Out of memory. return; // Since we're in the middle of processing messages, and since out-of-memory is so rare, // it seems justifiable not to have any error reporting and instead just avoid launching // the new thread. // Since above didn't return, the launch of the new thread is now considered unavoidable. // See MsgSleep() for comments about the following section. TCHAR ErrorLevel_saved[ERRORLEVEL_SAVED_SIZE]; tcslcpy(ErrorLevel_saved, g_ErrorLevel->Contents(), _countof(ErrorLevel_saved)); InitNewThread(0, false, true, func.mJumpToLine->mActionType); // v1.0.38.04: Below was added to maximize responsiveness to incoming messages. The reasoning // is similar to why the same thing is done in MsgSleep() prior to its launch of a thread, so see // MsgSleep for more comments: g_script.mLastScriptRest = g_script.mLastPeekTime = GetTickCount(); DEBUGGER_STACK_PUSH(func.mJumpToLine, func.mName) // ExprTokenType aResultToken; // ExprTokenType &aResultToken = aResultToken_to_return ; func.Call(&aResultToken); // Call the UDF. DEBUGGER_STACK_POP() switch (aFuncAndToken->mToken.symbol) { case SYM_VAR: // Caller has ensured that any SYM_VAR's Type() is VAR_NORMAL. if (_tcslen(aFuncAndToken->mToken.var->Contents())) { aFuncAndToken->result_to_return_dll = (LPTSTR )realloc((LPTSTR )aFuncAndToken->result_to_return_dll,_tcslen(aFuncAndToken->mToken.var->Contents())*sizeof(TCHAR)); _tcscpy(aFuncAndToken->result_to_return_dll,aFuncAndToken->mToken.var->Contents()); // Contents() vs. mContents to support VAR_CLIPBOARD, and in case mContents needs to be updated by Contents(). } else if (aFuncAndToken->result_to_return_dll) *aFuncAndToken->result_to_return_dll = '\0'; break; case SYM_STRING: case SYM_OPERAND: if (_tcslen(aFuncAndToken->mToken.marker)) { aFuncAndToken->result_to_return_dll = (LPTSTR )realloc((LPTSTR )aFuncAndToken->result_to_return_dll,_tcslen(aFuncAndToken->mToken.marker)*sizeof(TCHAR)); _tcscpy(aFuncAndToken->result_to_return_dll,aFuncAndToken->mToken.marker); } else if (aFuncAndToken->result_to_return_dll) *aFuncAndToken->result_to_return_dll = '\0'; break; case SYM_INTEGER: aFuncAndToken->result_to_return_dll = (LPTSTR )realloc((LPTSTR )aFuncAndToken->result_to_return_dll,MAX_INTEGER_LENGTH); ITOA64(aFuncAndToken->mToken.value_int64, aFuncAndToken->result_to_return_dll); break; case SYM_FLOAT: result_to_return_dll = (LPTSTR )realloc((LPTSTR )aFuncAndToken->result_to_return_dll,MAX_INTEGER_LENGTH); sntprintf(aFuncAndToken->result_to_return_dll, MAX_NUMBER_SIZE, g->FormatFloat, aFuncAndToken->mToken.value_double); break; //case SYM_OBJECT: // L31: Treat objects as empty strings (or TRUE where appropriate). default: // Not an operand: continue on to return the default at the bottom. if (aFuncAndToken->result_to_return_dll) *aFuncAndToken->result_to_return_dll = '\0'; } //Var::FreeAndRestoreFunctionVars(func, var_backup, var_backup_count); ResumeUnderlyingThread(ErrorLevel_saved); return; }