//********************************************************************* //* Microsoft Windows ** //* Copyright(c) Microsoft Corp., 1999 ** //********************************************************************* // // API.CPP - Header for the implementation of CAPI // // HISTORY: // // 1/27/99 a-jaswed Created. // #include "api.h" #include "appdefs.h" #include "dispids.h" #include "msobmain.h" #include "resource.h" #include // bugbug SHGetFolderPath should be used in the future #include #include // // List of characters that are not legal in netnames. // static const WCHAR IllegalNetNameChars[] = L"\"/\\[]:|<>+=;,.?* "; #define REGSTR_PATH_COMPUTERNAME \ L"System\\CurrentControlSet\\Control\\ComputerName\\ComputerName" #define REGSTR_PATH_ACTIVECOMPUTERNAME \ L"System\\CurrentControlSet\\Control\\ComputerName\\ActiveComputerName" #define REGSTR_PATH_TCPIP_PARAMETERS \ L"System\\CurrentControlSet\\Services\\Tcpip\\Parameters" #define REGSTR_PATH_VOLATILEENVIRONMENT \ L"VolatileEnvironment" #define REGSTR_VALUE_HOSTNAME L"Hostname" #define REGSTR_VALUE_LOGONSERVER L"LOGONSERVER" DISPATCHLIST APIExternalInterface[] = { {L"SaveFile", DISPID_API_SAVEFILE }, {L"SaveFileByCSIDL", DISPID_API_SAVEFILEBYCSIDL }, {L"get_INIKey", DISPID_API_GET_INIKEY }, {L"get_RegValue", DISPID_API_GET_REGVALUE }, {L"set_RegValue", DISPID_API_SET_REGVALUE }, {L"DeleteRegValue", DISPID_API_DELETEREGVALUE }, {L"DeleteRegKey", DISPID_API_DELETEREGKEY }, {L"get_SystemDirectory", DISPID_API_GET_SYSTEMDIRECTORY }, {L"get_CSIDLDirectory", DISPID_API_GET_CSIDLDIRECTORY }, {L"LoadFile", DISPID_API_LOADFILE, }, {L"get_UserDefaultLCID", DISPID_API_GET_USERDEFAULTLCID }, {L"get_ComputerName", DISPID_API_GET_COMPUTERNAME }, {L"set_ComputerName", DISPID_API_SET_COMPUTERNAME }, {L"FlushRegKey", DISPID_API_FLUSHREGKEY }, {L"ValidateComputername", DISPID_API_VALIDATECOMPUTERNAME }, {L"OEMComputername", DISPID_API_OEMCOMPUTERNAME }, {L"FormatMessage", DISPID_API_FORMATMESSAGE }, {L"set_ComputerDesc", DISPID_API_SET_COMPUTERDESC }, {L"get_UserDefaultUILanguage", DISPID_API_GET_USERDEFAULTUILANGUAGE } }; ///////////////////////////////////////////////////////////// // CAPI::CAPI CAPI::CAPI(HINSTANCE hInstance) { m_cRef = 0; } ///////////////////////////////////////////////////////////// // CAPI::~CAPI CAPI::~CAPI() { MYASSERT(m_cRef == 0); } //////////////////////////////////////////////// //////////////////////////////////////////////// //// GET / SET :: APILocale //// HRESULT CAPI::SaveFile(LPCWSTR szPath, LPCWSTR szURL, LPCWSTR szNewFileName) { WCHAR szFilePath[MAX_PATH]; lstrcpy(szFilePath, szPath); lstrcat(szFilePath, szNewFileName); return URLDownloadToFile(NULL, szURL, szFilePath, 0, NULL); } //SHGetSpecialFolderPath is only available if you have the new shell32.dll that came with IE 4.0 typedef BOOL (WINAPI* PFNSHGetPath)(HWND hwndOwner, LPWSTR lpszPath, int nFolder, BOOL fCreate); // bugbug SHGetFolderPath should be used in the future HRESULT CAPI::WrapSHGetSpecialFolderPath(HWND hwndOwner, LPWSTR lpszPath, int nFolder, BOOL fCreate) { HRESULT hr = E_NOTIMPL; HINSTANCE hShell32 = LoadLibrary(L"SHELL32.DLL"); if (NULL != hShell32) { PFNSHGetPath pfnGetPath = (PFNSHGetPath)GetProcAddress(hShell32, "SHGetSpecialFolderPathW"); if (NULL != pfnGetPath) { hr = pfnGetPath(hwndOwner, lpszPath, nFolder, fCreate) ? S_OK : E_FAIL; } FreeLibrary(hShell32); } return hr; } HRESULT CAPI::SaveFile(INT iCSIDLPath, BSTR bstrURL, BSTR bstrNewFileName) { WCHAR szFilePath[MAX_PATH]; // bugbug should we always create this? HRESULT hr = WrapSHGetSpecialFolderPath(NULL, szFilePath, iCSIDLPath, TRUE); if (FAILED(hr)) return (hr); lstrcat(szFilePath, L"\\"); return SaveFile(szFilePath, bstrURL, bstrNewFileName); } HRESULT CAPI::SaveFile(BSTR bstrPath, BSTR bstrURL) { WCHAR szURLPath[MAX_PATH]; lstrcpy(szURLPath, bstrURL); LPWSTR pchFileName = wcsrchr(szURLPath, L'/'); if (NULL != pchFileName) { *pchFileName++; return SaveFile(bstrPath, szURLPath, pchFileName); } else return E_FAIL; } HRESULT CAPI::SaveFile(INT iCSIDLPath, BSTR bstrURL) { WCHAR szURLPath[MAX_PATH]; WCHAR szFilePath[MAX_PATH]; // bugbug should we always create this? HRESULT hr = WrapSHGetSpecialFolderPath(NULL, szFilePath, iCSIDLPath, TRUE); if (FAILED(hr)) return (hr); lstrcpy(szURLPath, bstrURL); LPWSTR pchFileName = wcsrchr(szURLPath, L'/'); if (NULL != pchFileName) { *pchFileName++; lstrcat(szFilePath, L"\\"); return SaveFile(szFilePath, szURLPath, pchFileName); } else return E_FAIL; } HRESULT CAPI::get_INIKey(BSTR bstrINIFileName, BSTR bstrSectionName, BSTR bstrKeyName, LPVARIANT pvResult) { WCHAR szItem[1024]; //bugbug bad constants VariantInit(pvResult); if (GetPrivateProfileString(bstrSectionName, bstrKeyName, L"", szItem, MAX_CHARS_IN_BUFFER(szItem), bstrINIFileName)) { V_VT(pvResult) = VT_BSTR; V_BSTR(pvResult) = SysAllocString(szItem); return S_OK; } else return S_FALSE; } bool VerifyHKEY(HKEY hkey) { if (HKEY_CLASSES_ROOT == hkey || HKEY_CURRENT_USER == hkey || HKEY_LOCAL_MACHINE == hkey || HKEY_USERS == hkey || HKEY_PERFORMANCE_DATA == hkey || HKEY_CURRENT_CONFIG == hkey || HKEY_DYN_DATA == hkey) return true; return false; } HRESULT CAPI::FlushRegKey(HKEY hkey) { DWORD dwResult; dwResult = RegFlushKey(hkey); return ERROR_SUCCESS == dwResult ? S_OK : E_FAIL; } HRESULT CAPI::set_RegValue(HKEY hkey, BSTR bstrSubKey, BSTR bstrValue, LPVARIANT pvData) { if (!VerifyHKEY(hkey)) return E_INVALIDARG; DWORD dwResult, dwData; switch (V_VT(pvData)) { default: dwResult = E_FAIL; break; case VT_R8: dwData = (DWORD) V_R8(pvData); dwResult = SHSetValue(hkey, bstrSubKey, bstrValue, REG_DWORD, (LPVOID) &dwData, sizeof(dwData)); break; case VT_I4: dwResult = SHSetValue(hkey, bstrSubKey, bstrValue, REG_DWORD, (LPVOID) &V_I4(pvData), sizeof(V_I4(pvData))); break; case VT_BSTR: dwResult = SHSetValue(hkey, bstrSubKey, bstrValue, REG_SZ, (LPVOID) (V_BSTR(pvData)), BYTES_REQUIRED_BY_SZ(V_BSTR(pvData))); break; } return ERROR_SUCCESS == dwResult ? S_OK : E_FAIL; } HRESULT CAPI::get_RegValue(HKEY hkey, BSTR bstrSubKey, BSTR bstrValue, LPVARIANT pvResult) { if (!VerifyHKEY(hkey)) return E_INVALIDARG; DWORD dwType = REG_DWORD, cbData = 1024; BYTE rgbData[1024]; // bugbug data size HRESULT hr = ERROR_SUCCESS == SHGetValue(hkey, bstrSubKey, bstrValue, &dwType, (LPVOID) rgbData, &cbData) ? S_OK : E_FAIL; VariantInit(pvResult); switch (dwType) { default: case REG_DWORD: V_VT(pvResult) = VT_I4; V_I4(pvResult) = (SUCCEEDED(hr) && cbData >= sizeof(long)) ? * (long *) &rgbData : 0; break; case REG_SZ: V_VT(pvResult) = VT_BSTR; V_BSTR(pvResult) = SysAllocString(SUCCEEDED(hr) ? (LPCWSTR) rgbData : L""); break; } return hr; } HRESULT CAPI::DeleteRegKey(HKEY hkey, BSTR bstrSubKey) { if (!VerifyHKEY(hkey)) return E_INVALIDARG; return ERROR_SUCCESS == SHDeleteKey(hkey, bstrSubKey) ? S_OK : E_FAIL; } HRESULT CAPI::DeleteRegValue(HKEY hkey, BSTR bstrSubKey, BSTR bstrValue) { if (!VerifyHKEY(hkey)) return E_INVALIDARG; return ERROR_SUCCESS == SHDeleteValue(hkey, bstrSubKey, bstrValue) ? S_OK : E_FAIL; } HRESULT CAPI::get_SystemDirectory(LPVARIANT pvResult) { WCHAR szSysPath[MAX_PATH]; if (0 == GetSystemDirectory(szSysPath, MAX_PATH)) return E_FAIL; V_VT(pvResult) = VT_BSTR; V_BSTR(pvResult) = SysAllocString(szSysPath); return S_OK; }; HRESULT CAPI::get_CSIDLDirectory(UINT iCSIDLPath, LPVARIANT pvResult) { WCHAR szSysPath[MAX_PATH]; // bugbug should we always create this? HRESULT hr = WrapSHGetSpecialFolderPath(NULL, szSysPath, iCSIDLPath, TRUE); V_VT(pvResult) = VT_BSTR; V_BSTR(pvResult) = SysAllocString(SUCCEEDED(hr) ? (LPCWSTR) szSysPath : L""); return hr ; }; HRESULT CAPI::LoadFile(BSTR bstrPath, LPVARIANT pvResult) { HANDLE fh = INVALID_HANDLE_VALUE; HRESULT hr = E_FAIL; VariantInit(pvResult); V_VT(pvResult) = VT_BSTR; V_BSTR(pvResult) = NULL; fh = CreateFile(bstrPath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (fh != INVALID_HANDLE_VALUE) { DWORD cbSizeHigh = 0; DWORD cbSizeLow = GetFileSize(fh, &cbSizeHigh); BYTE* pbContents = new BYTE[cbSizeLow+1]; // We don't plan to read files greater than a DWORD in length, but we // want to know if we do. MYASSERT(0 == cbSizeHigh); if (NULL != pbContents) { if (ReadFile(fh, pbContents, cbSizeLow, &cbSizeHigh, NULL)) { // File contains ANSI chars // USES_CONVERSION; LPSTR szContents = (LPSTR) pbContents; pbContents[cbSizeLow] = '\0'; // Make sure there's no imbedded NULs because we rely on lstrlen MYASSERT( strlen((const char *)pbContents) == cbSizeLow ); V_BSTR(pvResult) = SysAllocString(A2W(szContents)); if (V_BSTR(pvResult) ) { hr = S_OK; } szContents = NULL; } delete [] pbContents; pbContents = NULL; } CloseHandle(fh); fh = INVALID_HANDLE_VALUE; } return hr; } HRESULT CAPI::get_UserDefaultLCID(LPVARIANT pvResult) { VariantInit(pvResult); V_VT(pvResult) = VT_I4; V_I4(pvResult) = GetUserDefaultLCID(); return S_OK; }; STDMETHODIMP CAPI::get_UserDefaultUILanguage( LPVARIANT pvResult ) { if (pvResult != NULL) { VariantInit(pvResult); V_VT(pvResult) = VT_I4; V_I4(pvResult) = GetUserDefaultUILanguage(); } return S_OK; } HRESULT CAPI::get_ComputerName( LPVARIANT pvResult ) { HRESULT hr = S_OK; WCHAR szComputerName[MAX_COMPUTERNAME_LENGTH + 1]; DWORD cch = sizeof(szComputerName) / sizeof(WCHAR); if (! ::GetComputerName( szComputerName, &cch)) { DWORD dwErr = ::GetLastError(); TRACE1(L"GetComputerName failed (0x%08X)", dwErr); szComputerName[0] = '\0'; hr = HRESULT_FROM_WIN32(dwErr); } if (SUCCEEDED(hr)) { V_VT(pvResult) = VT_BSTR; V_BSTR(pvResult) = SysAllocString(szComputerName); if (NULL == V_BSTR(pvResult)) { hr = E_OUTOFMEMORY; } } return hr; } ////////////////////////////////////////////////////////////////////////////// // // set_ComputerName // // Sets the computer name to a given string. SetComputerNameEx adjusts most // of the registry entries. However, the following need to be changed // directly because WinLogon changes them prior to running msoobe.exe: // * System\CurrentControlSet\Control\ComputerName\\ActiveComputerName // \ComputerName // * HKLM\System\CurrentControlSet\Services\Tcpip\Parameters // \Hostname // * HKEY_CURRENT_USER\VolatileEnvironment // \LOGONSERVER // // The ActiveComputerName key contains the name currently used by the computer // and returned by GetComputerName. // // The Tcpip\Parameters\Hostname value contains the non-volatile hostname // returned by ??. // // The LOGONSERVER value is used as the value of the LOGONSERVER environment // variable. // HRESULT CAPI::set_ComputerName( BSTR bstrComputerName ) { HRESULT hr = S_OK; LRESULT lResult; HKEY hkey = NULL; MYASSERT(NULL != bstrComputerName); if ( NULL == bstrComputerName || MAX_COMPUTERNAME_LENGTH < lstrlen((LPCWSTR)bstrComputerName) ) { return E_INVALIDARG; } // Trim spaces before we use the name StrTrim(bstrComputerName, TEXT(" ")); // SetComputerNameEx validates the name,sets // HKLM\System\CurrentControlSet\Control\ComputerName\ComputerName, and // changes the appropriate network registry entries. if (! ::SetComputerNameEx(ComputerNamePhysicalDnsHostname, (LPCWSTR)bstrComputerName) ) { DWORD dwErr = ::GetLastError(); TRACE2(L"SetComputerNameEx(%s) failed (0x%08X)", (LPCWSTR)bstrComputerName, dwErr ); return HRESULT_FROM_WIN32(dwErr); } // The following keys must be set explicitly because SetComputerNameEx does // not set them. // // HKLM\System\CurrentControlSet\Control\ComputerName\ActiveComputerName // must be set because it is the key that is used to determine the // current computer name. // lResult = RegOpenKeyEx(HKEY_LOCAL_MACHINE, REGSTR_PATH_ACTIVECOMPUTERNAME, 0, KEY_WRITE, &hkey ); if (ERROR_SUCCESS == lResult) { lResult = RegSetValueEx(hkey, REGSTR_VAL_COMPUTERNAME, 0, REG_SZ, (LPBYTE)bstrComputerName, BYTES_REQUIRED_BY_SZ(bstrComputerName) ); RegCloseKey(hkey); hkey = NULL; } if (ERROR_SUCCESS != lResult) { TRACE3(L"Failed to set %s to %s (0x%08X)\n", REGSTR_VAL_COMPUTERNAME, (LPCWSTR)bstrComputerName, lResult ); } // HKLM\System\CurrentControlSet\Services\Tcpip\Parameters\Hostname // contains the volatile hostname (ie this is the entry that is changed on // the fly) Winlogon has already updated this entry during boot so we // must update it ourselves. // lResult = RegOpenKeyEx(HKEY_LOCAL_MACHINE, REGSTR_PATH_TCPIP_PARAMETERS, 0, KEY_WRITE, &hkey ); if (ERROR_SUCCESS == lResult) { lResult = RegSetValueEx(hkey, REGSTR_VALUE_HOSTNAME, 0, REG_SZ, (LPBYTE)bstrComputerName, BYTES_REQUIRED_BY_SZ(bstrComputerName) ); RegCloseKey(hkey); hkey = NULL; } if (ERROR_SUCCESS != lResult) { TRACE3(L"Failed to set %s to %s (0x%08X)\n", REGSTR_VALUE_HOSTNAME, (LPCWSTR)bstrComputerName, lResult ); } // Key should have been closed already. // MYASSERT(NULL == hkey); if (!SetAccountsDomainSid(0, bstrComputerName)) { TRACE(L"SetAccountsDomainSid failed\n\r"); } return S_OK; } HRESULT CAPI::ValidateComputername(BSTR bstrComputername) { HRESULT hr = E_FAIL; UINT Length,u; if (!bstrComputername) return hr; // Trim spaces before validation. StrTrim(bstrComputername, TEXT(" ")); Length = lstrlen(bstrComputername); if ((Length == 0) || (Length > MAX_COMPUTERNAME_LENGTH)) return hr; u = 0; hr = S_OK; while ((hr == S_OK) && (u < Length)) { // // Control chars are invalid, as are characters in the illegal chars list. // if((bstrComputername[u] < L' ') || wcschr(IllegalNetNameChars,bstrComputername[u])) { hr = E_FAIL; } u++; } return hr; } STDMETHODIMP CAPI::OEMComputername() { WCHAR szIniFile[MAX_PATH] = L""; WCHAR szComputerName[MAX_COMPUTERNAME_LENGTH + 1]; HRESULT hr = E_FAIL; // Get the name from the INI file. if (GetCanonicalizedPath(szIniFile, INI_SETTINGS_FILENAME)) { if (GetPrivateProfileString(USER_INFO_KEYNAME, L"Computername", L"\0", szComputerName, MAX_CHARS_IN_BUFFER(szComputerName), szIniFile) != 0) { if (SUCCEEDED(hr = ValidateComputername(szComputerName))) { hr = set_ComputerName(szComputerName); if (hr != S_OK) { TRACE2(TEXT("OEMComputername: set_ComputerName on %s failed with %lx"), szComputerName, hr); } } else { TRACE1(TEXT("OEMComputername: Computername %s is invalid"), szComputerName); } } } return hr; } STDMETHODIMP CAPI::FormatMessage( LPVARIANT pvResult, // message buffer BSTR bstrSource, // message source int cArgs, // number of inserts VARIANTARG *rgArgs // array of message inserts ) { DWORD dwErr; BSTR* rgbstr = NULL; LPTSTR str = NULL; if (pvResult == NULL) { return S_OK; } VariantInit(pvResult); if (bstrSource == NULL) { return E_FAIL; } if (cArgs > 0 && rgArgs != NULL) { rgbstr = (BSTR*)LocalAlloc(LPTR, cArgs * sizeof(BSTR)); if (rgbstr == NULL) { return E_FAIL; } // Since IDispatch::Invoke gets argument right to left, and // since we need to pass argument to FormatMessage left to right, // we need to reverse the order of argument while copying. for (int i = 0; i < cArgs; i++) { rgbstr[cArgs - 1 - i] = V_BSTR(&rgArgs[i]); } } dwErr = ::FormatMessage(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_ARGUMENT_ARRAY, bstrSource, 0, 0, (LPTSTR)&str, MAX_PATH, (va_list *)rgbstr ); if (dwErr != 0) { V_VT(pvResult) = VT_BSTR; V_BSTR(pvResult) = SysAllocString(str); } if (str != NULL) { LocalFree(str); } if (rgbstr != NULL) { LocalFree(rgbstr); } return (dwErr != 0 ? S_OK : E_FAIL); } STDMETHODIMP CAPI::set_ComputerDesc(BSTR bstrComputerDesc) { WCHAR szKeyName[] = REG_KEY_OOBE_TEMP; HKEY hKey; if ( bstrComputerDesc ) { if ( RegCreateKeyEx(HKEY_LOCAL_MACHINE, szKeyName, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey, NULL) == ERROR_SUCCESS ) { RegSetValueEx(hKey, REG_VAL_COMPUTERDESCRIPTION, 0, REG_SZ, (LPBYTE) bstrComputerDesc, BYTES_REQUIRED_BY_SZ(bstrComputerDesc)); RegFlushKey(hKey); RegCloseKey(hKey); } } return S_OK; } ///////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////// /////// IUnknown implementation /////// /////// ///////////////////////////////////////////////////////////// // CAPI::QueryInterface STDMETHODIMP CAPI::QueryInterface(REFIID riid, LPVOID* ppvObj) { // must set out pointer parameters to NULL *ppvObj = NULL; if ( riid == IID_IUnknown) { AddRef(); *ppvObj = (IUnknown*)this; return ResultFromScode(S_OK); } if (riid == IID_IDispatch) { AddRef(); *ppvObj = (IDispatch*)this; return ResultFromScode(S_OK); } // Not a supported interface return ResultFromScode(E_NOINTERFACE); } ///////////////////////////////////////////////////////////// // CAPI::AddRef STDMETHODIMP_(ULONG) CAPI::AddRef() { return ++m_cRef; } ///////////////////////////////////////////////////////////// // CAPI::Release STDMETHODIMP_(ULONG) CAPI::Release() { return --m_cRef; } ///////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////// /////// IDispatch implementation /////// /////// ///////////////////////////////////////////////////////////// // CAPI::GetTypeInfo STDMETHODIMP CAPI::GetTypeInfo(UINT, LCID, ITypeInfo**) { return E_NOTIMPL; } ///////////////////////////////////////////////////////////// // CAPI::GetTypeInfoCount STDMETHODIMP CAPI::GetTypeInfoCount(UINT* pcInfo) { return E_NOTIMPL; } ///////////////////////////////////////////////////////////// // CAPI::GetIDsOfNames STDMETHODIMP CAPI::GetIDsOfNames(REFIID riid, OLECHAR** rgszNames, UINT cNames, LCID lcid, DISPID* rgDispId) { HRESULT hr = DISP_E_UNKNOWNNAME; rgDispId[0] = DISPID_UNKNOWN; for (int iX = 0; iX < sizeof(APIExternalInterface)/sizeof(DISPATCHLIST); iX ++) { if(lstrcmp(APIExternalInterface[iX].szName, rgszNames[0]) == 0) { rgDispId[0] = APIExternalInterface[iX].dwDispID; hr = NOERROR; break; } } // Set the disid's for the parameters if (cNames > 1) { // Set a DISPID for function parameters for (UINT i = 1; i < cNames ; i++) rgDispId[i] = DISPID_UNKNOWN; } return hr; } ///////////////////////////////////////////////////////////// // CAPI::Invoke HRESULT CAPI::Invoke ( DISPID dispidMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS* pdispparams, VARIANT* pvarResult, EXCEPINFO* pexcepinfo, UINT* puArgErr ) { // Assume everything is hunky-dory. Only return an HRESULT other than S_OK // in case of a catastrophic failure. Result codes should be returned to // script via pvarResult. // HRESULT hr = S_OK; switch(dispidMember) { case DISPID_API_SAVEFILE: { TRACE(L"DISPID_API_SAVEFILE\n"); if (NULL != pdispparams) { if (2 < pdispparams->cArgs) SaveFile(V_BSTR(&pdispparams->rgvarg[2]), V_BSTR(&pdispparams->rgvarg[1]), V_BSTR(&pdispparams->rgvarg[0])); else if (1 < pdispparams->cArgs) SaveFile(V_BSTR(&pdispparams->rgvarg[1]), V_BSTR(&pdispparams->rgvarg[0])); } break; } // bugbug If VariantChangeType returns DISP_E_TYPEMISMATCH, the implementor would set *puArgErr to 0 (indicating the argument in error) and return DISP_E_TYPEMISMATCH from IDispatch::Invoke. case DISPID_API_SAVEFILEBYCSIDL: { TRACE(L"DISPID_API_SAVEFILEBYCSIDL\n"); if (NULL != pdispparams) { VARIANTARG vaConverted; VariantInit(&vaConverted); if (2 < pdispparams->cArgs) { hr = VariantChangeType(&vaConverted, &pdispparams->rgvarg[2], 0, VT_I4); if (SUCCEEDED(hr)) hr = SaveFile(V_I4(&vaConverted), V_BSTR(&pdispparams->rgvarg[1]), V_BSTR(&pdispparams->rgvarg[0])); } else if (1 < pdispparams->cArgs) { hr = VariantChangeType(&vaConverted, &pdispparams->rgvarg[1], 0, VT_I4); if (SUCCEEDED(hr)) hr = SaveFile(V_I4(&vaConverted), V_BSTR(&pdispparams->rgvarg[0])); } } hr = S_OK; // don't cause script engine to throw exception break; } case DISPID_API_GET_INIKEY: { TRACE(L"DISPID_API_GET_INIKEY\n"); if (pdispparams != NULL && pvarResult != NULL) { if (pdispparams->cArgs > 2) { get_INIKey( V_BSTR(&pdispparams->rgvarg[2]), V_BSTR(&pdispparams->rgvarg[1]), V_BSTR(&pdispparams->rgvarg[0]), pvarResult ); } else if (pdispparams->cArgs == 2) { BSTR bstrFile = SysAllocStringLen(NULL, MAX_PATH); if (bstrFile) { if (GetCanonicalizedPath(bstrFile, INI_SETTINGS_FILENAME)) { get_INIKey( bstrFile, V_BSTR(&pdispparams->rgvarg[1]), V_BSTR(&pdispparams->rgvarg[0]), pvarResult ); } SysFreeString(bstrFile); } } } break; } case DISPID_API_SET_REGVALUE: TRACE(L"DISPID_API_SET_REGVALUE: "); if (NULL != pdispparams && 3 < pdispparams->cArgs) { BSTR bstrSubKey = NULL; BSTR bstrValueName = NULL; BOOL bValid = TRUE; switch (V_VT(&pdispparams->rgvarg[1])) { case VT_NULL: bstrValueName = NULL; break; case VT_BSTR: bstrValueName = V_BSTR(&pdispparams->rgvarg[1]); break; default: bValid = FALSE; } bstrSubKey = V_BSTR(&pdispparams->rgvarg[2]); if (bValid) { TRACE2(L"%s, %s\n", bstrSubKey, bstrValueName); set_RegValue((HKEY) (DWORD_PTR) V_R8(&pdispparams->rgvarg[3]), bstrSubKey, bstrValueName, &pdispparams->rgvarg[0]); } } break; case DISPID_API_GET_REGVALUE: TRACE(L"DISPID_API_GET_REGVALUE: "); if (NULL != pdispparams && NULL != pvarResult && 2 < pdispparams->cArgs) { BSTR bstrSubKey = NULL; BSTR bstrValueName = NULL; BOOL bValid = TRUE; switch (V_VT(&pdispparams->rgvarg[0])) { case VT_NULL: bstrValueName = NULL; break; case VT_BSTR: bstrValueName = V_BSTR(&pdispparams->rgvarg[0]); break; default: bValid = FALSE; } bstrSubKey = V_BSTR(&pdispparams->rgvarg[1]); if (bValid) { TRACE2(L"%s: %s", bstrSubKey, bstrValueName); get_RegValue((HKEY) (DWORD_PTR) V_R8(&pdispparams->rgvarg[2]), bstrSubKey, bstrValueName, pvarResult); } } break; case DISPID_API_DELETEREGVALUE: TRACE(L"DISPID_API_DELETEREGVALUE\n"); if (NULL != pdispparams && 1 < pdispparams->cArgs) DeleteRegValue((HKEY) (DWORD_PTR) V_R8(&pdispparams->rgvarg[2]), V_BSTR(&pdispparams->rgvarg[1]), V_BSTR(&pdispparams->rgvarg[0])); break; case DISPID_API_DELETEREGKEY: TRACE(L"DISPID_API_DELETEREGKEY\n"); if (NULL != pdispparams && 1 < pdispparams->cArgs) DeleteRegKey((HKEY) (DWORD_PTR) V_R8(&pdispparams->rgvarg[1]), V_BSTR(&pdispparams->rgvarg[0])); break; case DISPID_API_GET_SYSTEMDIRECTORY: TRACE(L"DISPID_API_GET_SYSTEMDIRECTORY\n"); if (NULL != pvarResult) get_SystemDirectory(pvarResult); break; case DISPID_API_GET_CSIDLDIRECTORY: TRACE(L"DISPID_API_GET_CSIDLDIRECTORY\n"); if (NULL != pdispparams && 0 < pdispparams->cArgs && pvarResult != NULL) get_CSIDLDirectory(V_I4(&pdispparams->rgvarg[0]), pvarResult); break; case DISPID_API_LOADFILE: TRACE(L"DISPID_API_LOADFILE\n"); if (NULL != pdispparams && 0 < pdispparams->cArgs && pvarResult != NULL) { LoadFile(V_BSTR(&pdispparams->rgvarg[0]), pvarResult); } break; case DISPID_API_GET_USERDEFAULTLCID: TRACE(L"DISPID_API_GET_USERDEFAULTLCID\n"); if (pvarResult != NULL) get_UserDefaultLCID(pvarResult); break; case DISPID_API_GET_COMPUTERNAME: TRACE(L"DISPID_API_GET_COMPUTERNAME\n"); if (NULL != pvarResult) { get_ComputerName(pvarResult); } break; case DISPID_API_SET_COMPUTERNAME: TRACE(L"DISPID_API_SET_COMPUTERNAME\n"); if (pdispparams && &(pdispparams[0].rgvarg[0])) { hr = set_ComputerName(pdispparams[0].rgvarg[0].bstrVal); if (pvarResult) { VariantInit(pvarResult); V_VT(pvarResult) = VT_BOOL; V_BOOL(pvarResult) = Bool2VarBool(SUCCEEDED(hr)); } } hr = S_OK; // don't cause an exception in the scripting engine. break; case DISPID_API_FLUSHREGKEY: TRACE(L"DISPID_API_FLUSHREGKEY\n"); if (pdispparams && &(pdispparams[0].rgvarg[0])) { FlushRegKey((HKEY) (DWORD_PTR) V_R8(&pdispparams->rgvarg[0])); } break; case DISPID_API_VALIDATECOMPUTERNAME: TRACE(L"DISPID_API_VALIDATECOMPUTERNAME\n"); if (pdispparams && (0 < pdispparams->cArgs)) { hr = ValidateComputername(pdispparams[0].rgvarg[0].bstrVal); if (pvarResult) { VariantInit(pvarResult); V_VT(pvarResult) = VT_BOOL; V_BOOL(pvarResult) = Bool2VarBool(SUCCEEDED(hr)); } } hr = S_OK; // don't cause an exception in the scripting engine. break; case DISPID_API_OEMCOMPUTERNAME: TRACE(L"DISPID_API_OEMCOMPUTERNAME"); hr = OEMComputername(); if (pvarResult) { VariantInit(pvarResult); V_VT(pvarResult) = VT_BOOL; V_BOOL(pvarResult) = Bool2VarBool(SUCCEEDED(hr)); } hr = S_OK; // don't cause an exception in the scripting engine. break; case DISPID_API_FORMATMESSAGE: TRACE(L"DISPID_API_FORMATMESSAGE"); if (pdispparams != NULL) { int cArgs = pdispparams->cArgs - 1; if (cArgs >= 0 && V_VT(&pdispparams->rgvarg[cArgs]) == VT_BSTR) { FormatMessage(pvarResult, V_BSTR(&pdispparams->rgvarg[cArgs]), cArgs, &pdispparams->rgvarg[0]); } } break; case DISPID_API_SET_COMPUTERDESC: TRACE(L"DISPID_API_SET_COMPUTERDESC\n"); if (pdispparams && &(pdispparams[0].rgvarg[0])) { hr = set_ComputerDesc(pdispparams[0].rgvarg[0].bstrVal); if (pvarResult) { VariantInit(pvarResult); V_VT(pvarResult) = VT_BOOL; V_BOOL(pvarResult) = Bool2VarBool(SUCCEEDED(hr)); } } hr = S_OK; // don't cause an exception in the scripting engine. break; case DISPID_API_GET_USERDEFAULTUILANGUAGE: TRACE(L"DISPID_API_GET_USERDEFAULTUILANGUAGE"); get_UserDefaultUILanguage(pvarResult); break; default: { hr = DISP_E_MEMBERNOTFOUND; break; } } return hr; }