// // Description: // Converts a BSTR array in a VARIANT to an equivalent array of PWSTRs. // // Parameters: // vtStringArray - A string array stored in a VARIANT that wraps a SAFEARRAY. // // pppWstrArray - On success, receives an array of PWSTR* populated with the // values from vtStringArray represented as PWSTRs. Caller must free with // HB_SAFE_FREE_ARRAY. // // pcWstrArray - On success, is set to the number of elements in pppWstrArray. // HRESULT VariantStringArrayToWstrArray(__in VARIANT vtStringArray, __out PWSTR** pppWstrArray, __out size_t* pcWstrArray) { HRESULT hr; SAFEARRAY* arrStrings; size_t cWstrArrayLocal = 0; size_t cbWstrArrayLocal; PWSTR* ppWstrArrayLocal = NULL; BSTR bstrCurrent; arrStrings = vtStringArray.parray; cWstrArrayLocal = arrStrings->rgsabound[0].cElements; hr = SizeTMult(cWstrArrayLocal, sizeof(PWSTR*), &cbWstrArrayLocal); if(HB_FAILED(hr)) { goto cleanexit; } ppWstrArrayLocal = (PWSTR*)malloc(cbWstrArrayLocal); if(!ppWstrArrayLocal) { hr = E_OUTOFMEMORY; goto cleanexit; } // // Zero out the array so that elements can be safely deleted if // initialization partway through. // memset(ppWstrArrayLocal, 0, cbWstrArrayLocal); for(size_t stringIndex = 0; stringIndex < cWstrArrayLocal; stringIndex++) { bstrCurrent = ((BSTR*)arrStrings->pvData)[stringIndex]; hr = BStrToPWchar(bstrCurrent, &ppWstrArrayLocal[stringIndex]); if(HB_FAILED(hr)) { goto cleanexit; } } *pppWstrArray = ppWstrArrayLocal; ppWstrArrayLocal = NULL; *pcWstrArray = cWstrArrayLocal; cWstrArrayLocal = 0; cleanexit: HB_SAFE_FREE_ARRAY(ppWstrArrayLocal, cWstrArrayLocal); return hr; }
// // Description: // Converts a BSTR to an equivalent PWSTR. // // Parameters: // bstr - A string represented as a BSTR. // // ppWStr - On success, is set to the PWSTR equivalent of bstr. Caller must // free with HB_SAFE_FREE. // HRESULT BStrToPWchar(__in BSTR bstr, __out PWSTR* ppWStr) { HRESULT hr; size_t cbWStr; PWSTR pWStrLocal = NULL; hr = SizeTMult(SysStringLen(bstr), sizeof(WCHAR), &cbWStr); if(HB_FAILED(hr)) { goto cleanexit; } // // Correct for additional NULL pointer // hr = SizeTAdd(cbWStr, sizeof(WCHAR), &cbWStr); if(HB_FAILED(hr)) { goto cleanexit; } pWStrLocal = (PWSTR)malloc(cbWStr); if(!pWStrLocal) { hr = E_OUTOFMEMORY; goto cleanexit; } hr = StringCbCopy(pWStrLocal, cbWStr, static_cast<wchar_t*>(bstr)); if(HB_FAILED(hr)) { goto cleanexit; } *ppWStr = pWStrLocal; pWStrLocal = NULL; cleanexit: HB_SAFE_FREE(pWStrLocal); return hr; }
// // Description: // Retrieves that the service manage uses to launch the YoNTMA binary as a // service. // // Parameters: // ppszServiceExecutionString - On success, contains the command line string // used to launch YoNTMA (including arguments). Caller must free with // HB_SAFE_FREE. // HRESULT GetServiceExecutionString(__out PTSTR* ppszServiceExecutionString) { HRESULT hr; DWORD rc; SC_HANDLE hService = NULL; LPQUERY_SERVICE_CONFIG pQueryServiceConfig = NULL; DWORD cbQueryServiceConfig; DWORD cbQueryServiceConfigRequired; PTSTR pszServiceExecutionStringLocal = NULL; size_t cchServiceExecutionStringLocal; size_t cbServiceExecutionStringLocal; hr = OpenYontmaService(&hService); if(HB_FAILED(hr)) { goto cleanexit; } QueryServiceConfig(hService, NULL, 0, &cbQueryServiceConfigRequired); rc = GetLastError(); // // QueryServiceConfig succeeded with a zero-sized buffer? Something is wrong. // if(rc == ERROR_SUCCESS) { hr = E_UNEXPECTED; goto cleanexit; } else if(rc != ERROR_INSUFFICIENT_BUFFER) { hr = HRESULT_FROM_WIN32(GetLastError()); goto cleanexit; } cbQueryServiceConfig = cbQueryServiceConfigRequired; pQueryServiceConfig = (LPQUERY_SERVICE_CONFIG)LocalAlloc(LMEM_FIXED, cbQueryServiceConfig); if(!pQueryServiceConfig) { hr = E_OUTOFMEMORY; goto cleanexit; } if(!QueryServiceConfig(hService, pQueryServiceConfig, cbQueryServiceConfig, &cbQueryServiceConfigRequired)) { hr = HRESULT_FROM_WIN32(GetLastError()); goto cleanexit; } cchServiceExecutionStringLocal = _tcslen(pQueryServiceConfig->lpBinaryPathName); hr = SizeTAdd(cchServiceExecutionStringLocal, 1, &cchServiceExecutionStringLocal); if(HB_FAILED(hr)) { goto cleanexit; } hr = SizeTMult(cchServiceExecutionStringLocal, sizeof(TCHAR), &cbServiceExecutionStringLocal); if(HB_FAILED(hr)) { goto cleanexit; } pszServiceExecutionStringLocal = (PTSTR)malloc(cbServiceExecutionStringLocal); if(!pszServiceExecutionStringLocal) { hr = E_OUTOFMEMORY; goto cleanexit; } hr = StringCchCopy(pszServiceExecutionStringLocal, cchServiceExecutionStringLocal, pQueryServiceConfig->lpBinaryPathName); if(HB_FAILED(hr)) { goto cleanexit; } *ppszServiceExecutionString = pszServiceExecutionStringLocal; pszServiceExecutionStringLocal = NULL; cleanexit: HB_SAFE_CLOSE_SERVICE_HANDLE(hService); HB_SAFE_LOCAL_FREE(pQueryServiceConfig); HB_SAFE_FREE(pszServiceExecutionStringLocal); return hr; }
/*++ ******************************************************************* E n u m P r i n t P r o c e s s o r D a t a t y p e s W Routine Description: Enumerates the data types supported by the print processor. Arguments: pName => server name pPrintProcessorName => print processor name Level => level of data to return (must be 1) pDatatypes => structure array to fill in cbBuf => length of structure array in bytes pcbNeeded => buffer length copied/required pcReturned => number of structures returned Return Value: TRUE if successful FALSE if failed - caller must use GetLastError for reason ******************************************************************* --*/ _Use_decl_annotations_ BOOL WINAPI EnumPrintProcessorDatatypes( LPWSTR pName, LPWSTR pPrintProcessorName, DWORD Level, LPBYTE pDatatypes, DWORD cbBuf, LPDWORD pcbNeeded, LPDWORD pcReturned ) { DATATYPES_INFO_1 *pInfo1 = (DATATYPES_INFO_1 *)pDatatypes; LPWSTR *pMyDatatypes = Datatypes; size_t cbTotal=0; ULONG cchBuf =0; LPBYTE pEnd; BOOL bRetVal = TRUE; HRESULT hr; size_t tempSizeT; UNREFERENCED_PARAMETER(pName); UNREFERENCED_PARAMETER(pPrintProcessorName); if ( NULL == pcbNeeded || NULL == pcReturned ) { SetLastError (ERROR_INVALID_PARAMETER); return FALSE; } /** Start assuming failure, no entries returned **/ *pcbNeeded = 0; *pcReturned = 0; if (Level != 1) { SetLastError(ERROR_INVALID_PARAMETER); return FALSE; } /** Add up the minimum buffer required **/ while (*pMyDatatypes) { if (FAILED(SizeTMult(wcslen(*pMyDatatypes), sizeof(WCHAR), &tempSizeT)) || FAILED(SizeTAdd(tempSizeT, sizeof(WCHAR), &tempSizeT)) || FAILED(SizeTAdd(tempSizeT, sizeof(DATATYPES_INFO_1), &tempSizeT)) || FAILED(SizeTAdd(cbTotal, tempSizeT, &cbTotal))) { SetLastError (ERROR_ARITHMETIC_OVERFLOW); bRetVal = FALSE; break; } pMyDatatypes++; } /** Set the buffer length returned/required **/ if (bRetVal && FAILED(SizeTToDWord(cbTotal, pcbNeeded))) { SetLastError (ERROR_ARITHMETIC_OVERFLOW); bRetVal = FALSE; } /** Fill in the array only if there is sufficient space **/ if (bRetVal && cbTotal <= cbBuf) { if ( NULL == pInfo1 ) //pInfo1 is same as pDatatypes { SetLastError (ERROR_INVALID_PARAMETER); bRetVal = FALSE; } else { /** Pick up pointer to end of the given buffer **/ pEnd = (LPBYTE)pInfo1 + cbBuf; /** Pick up our list of supported data types **/ pMyDatatypes = Datatypes; /** Fill in the given buffer. We put the data names at the end of the buffer, working towards the front. The structures are put at the front, working towards the end. **/ while (*pMyDatatypes) { if (FAILED(SizeTAdd(wcslen(*pMyDatatypes), 1, &tempSizeT)) || //+1 is for \0. FAILED(SizeTToDWord(tempSizeT, &cchBuf))) { SetLastError (ERROR_ARITHMETIC_OVERFLOW); bRetVal = FALSE; break; } pEnd -= cchBuf*sizeof(WCHAR); hr = StringCchCopy ( (LPWSTR)pEnd, cchBuf, *pMyDatatypes); if ( FAILED(hr) ) { // // For the hr values returned by StringCchCopy, the following macro // is sufficient // SetLastError (HRESULT_CODE(hr)); bRetVal = FALSE; break; } pInfo1->pName = (LPWSTR)pEnd; pInfo1++; (*pcReturned)++; pMyDatatypes++; } } } else { /** Caller didn't have large enough buffer, set error and return **/ SetLastError(ERROR_INSUFFICIENT_BUFFER); bRetVal = FALSE; } return bRetVal; }