Access violation reading from location in C++ - c++

Why is the last statement throwing Access Violation?
I wanted to write the status of a service into an XML file.
#define STR_SERVICE_STATUS_INPUT__XML_CONTENT _T("<SERVICE NAME = \"%s\" STARTUP_TYPE = \"0x%d\" />\r\n\r\n")
CString csWriteBufferTemp;
DWORD dwBufferSize;
DWORD dwBytesNeeded;
SC_HANDLE schHandle;
LPQUERY_SERVICE_CONFIG st_lpqscServiceInfo;
schHandle = OpenService(IN_schHandle, (CString)cArgentServices[i], SERVICE_QUERY_CONFIG);
bRC = QueryServiceConfig(schHandle, NULL, 0, &dwBytesNeeded);
dwBufferSize = dwBytesNeeded; //Size needed.
st_lpqscServiceInfo = (LPQUERY_SERVICE_CONFIG) LocalAlloc(LMEM_FIXED, dwBufferSize);
bRC = QueryServiceConfig(schHandle, st_lpqscServiceInfo, dwBufferSize, &dwBytesNeeded);
csWriteBufferTemp.Format(STR_SERVICE_STATUS_INPUT__XML_CONTENT__,st_lpqscServiceInfo->lpDisplayName,0);

You are almost certainly using the wrong string format parameter in _T("<SERVICE NAME = \"%S\" STARTUP_TYPE = \"0x%d\" />\r\n\r\n"). The lpServiceStartName member of SERVICE_QUERY_CONFIG and CString are both TCHAR-based so they should have matching character types regardless of whether your compiling in Unicode mode or not. In that case, you should be using %s instead of %S.

Thanks for all your replies and suggestions, I found the answer on another site. I don't know if this is the correct way but it works!
LPQUERY_SERVICE_CONFIG
st_lpqscServiceInfo;
SC_HANDLE schHandle;
st_lpqscServiceInfo = (LPQUERY_SERVICE_CONFIG) LocalAlloc(LPTR, 4096);
schHandle = OpenSCManager(IN_pszMachineName,SERVICES_ACTIVE_DATABASE, SERVICE_QUERY_CONFIG);
bRC = QueryServiceConfig(schHandle, st_lpqscServiceInfo, dwBufferSize, &dwBytesNeeded);
csWriteBufferTemp.Format(STR_SERVICE_STATUS_INPUT__XML_CONTENT__,st_lpqscServiceInfo->lpDisplayName,0);

Related

How can i create a dir in Documents folder? [C++]

Im trying to create a directory , or a subdirectory in the Documents folder.
PWSTR ppszPath; // variable to receive the path memory block pointer.
HRESULT hr = SHGetKnownFolderPath(FOLDERID_Documents, 0, NULL, &ppszPath);
std::wstring myPath;
if (SUCCEEDED(hr)) {
myPath = ppszPath; // make a local copy of the path
}
const wchar_t* str = myPath.c_str();
_bstr_t b(str);
int status = _mkdir(b+"\\New");
As you can see , I'm trying to create a new folder named "New" in Documents Folder.
The path to the documents is correct but the dir is not created.
This is using _bstr_t to avoid using Unicode, the new path is converted to ANSI and will be invalid unless the original path was ANSI, (or ASCII to be guaranteed)
Just pad L"\\New" and wide string functions to solve the problem.
You also have to free ppszPath as stated in documentation
std::wstring myPath;
wchar_t *ppszPath;
HRESULT hr = SHGetKnownFolderPath(FOLDERID_Documents, 0, NULL, &ppszPath);
if (SUCCEEDED(hr))
{
myPath = ppszPath;
CoTaskMemFree(ppszPath);
}//error checking?
myPath += L"\\New";
std::filesystem::create_directory(myPath)
//or _wmkdir(myPath.c_str());
The std::filesystem::path class understands Unicode just fine, so you don’t need to mess with any helpers there. Also, you need to check both function results to determine success or failure:
bool success = false;
PWSTR documents_path = nullptr;
if (SUCCEEDED( SHGetKnownFolderPath( FOLDERID_Documents, 0, NULL, &documents_path ) ))
{
using namespace std::filesystem;
success = create_directory( path{ documents_path } / "new_folder" );
CoTaskMemFree( documents_path );
documents_path = nullptr;
}
The result of the operation is indicated in the variable success.
I would personally separate the functions of obtaining the user’s Documents folder and the directory creation into two separate functions, but the above will do just fine.

Parsing wchar_t xml using Microsoft WebServices

I'm trying to parse a wide character string using WebServices.
HRESULT hr = NOERROR;
WS_ERROR* error = NULL;
WS_XML_READER* xmlReader = NULL;
// Create an error object for storing rich error information
hr = WsCreateError(
NULL,
0,
&error);
if (FAILED(hr))
{
goto Exit;
}
// Create an XML reader
hr = WsCreateReader(
NULL,
0,
&xmlReader,
error);
if (FAILED(hr))
{
goto Exit;
}
WCHAR* xml =
L"<?xml version='1.0' encoding='UTF-8' standalone='yes'?>"
"<Orders xmlns='http://example.com'>"
"<!-- Order #1 -->"
"<PurchaseOrder id='1'>"
"<Quantity>42</Quantity>"
"<ProductName>Toaster</ProductName>"
"</PurchaseOrder>"
"<!-- Order #2 -->"
"<PurchaseOrder id='2'>"
"<Quantity>5</Quantity>"
"<ProductName><![CDATA[Block&Tackle]></ProductName>"
"</PurchaseOrder>"
"</Orders>";
BYTE* bytes = (BYTE*)xml;
ULONG byteCount = (ULONG)wcslen(xml) * sizeof(WCHAR);
// Setup the source input
WS_XML_READER_BUFFER_INPUT bufferInput;
ZeroMemory(&bufferInput, sizeof(bufferInput));
bufferInput.input.inputType = WS_XML_READER_INPUT_TYPE_BUFFER;
bufferInput.encodedData = bytes;
bufferInput.encodedDataSize = byteCount;
// Setup the source encoding
WS_XML_READER_TEXT_ENCODING textEncoding;
ZeroMemory(&textEncoding, sizeof(textEncoding));
textEncoding.encoding.encodingType = WS_XML_READER_ENCODING_TYPE_TEXT;
textEncoding.charSet = WS_CHARSET_AUTO;
// Setup the reader
hr = WsSetInput(xmlReader, &textEncoding.encoding, &bufferInput.input, NULL, 0, error);
if (FAILED(hr))
{
goto Exit;
}
I've also tried to change textEncoding.charSet = WS_CHARSET_AUTO; to textEncoding.charSet = WS_CHARSET_UTF16LE;
The above code keeps failing while calling to WsReadNode (in the attached link), and the error message is "The data input was not in the expected format or did not have the expected value".
WsReadNode
I can't convert the WCHAR array to CHAR array as the XML may contain non ASCII characters.
The example xml has an encoding in the declaration
L"<?xml version='1.0' encoding='UTF-8' standalone='yes'?>"
Changing it to
L"<?xml version='1.0' encoding='UTF-16LE' standalone='yes'?>"
should fix the error.
https://learn.microsoft.com/es-es/windows/win32/api/webservices/ns-webservices-ws_xml_reader_buffer_input
https://learn.microsoft.com/es-es/windows/win32/api/webservices/ns-webservices-ws_xml_reader_text_encoding
https://learn.microsoft.com/es-es/windows/win32/api/webservices/ns-webservices-_ws_xml_reader_encoding
https://learn.microsoft.com/ru-ru/windows/win32/api/webservices/ne-webservices-ws_xml_reader_encoding_type
https://learn.microsoft.com/es-es/windows/win32/api/webservices/ne-webservices-ws_charset
For example on this ultimate you should use WS_CHARSET_UTF8 because on your XML you put encoding UTF8.
About ASCII, what about make something to replace non ASCII values to ASCII values ?
If you have problems with WCHAR to CHAR conversion, on this site you have a lot of info about this.

winapi - GetServiceKeyName returns empty service name

I'm trying to get service name from display name using winapi function GetServiceKeyName in C++ with the following code:
SC_HANDLE hSCManager = OpenSCManager(NULL,
NULL, // service control manager database
SC_MANAGER_CONNECT | SC_MANAGER_ENUMERATE_SERVICE |SC_MANAGER_QUERY_LOCK_STATUS | STANDARD_RIGHTS_READ);
LPTSTR lpServiceName;
LPCTSTR lpDisplayName = L"My service";
DWORD dwSizeNeeded = sizeof(lpDisplayName);
GetServiceKeyName(hSCManager, lpDisplayName, lpServiceName, &dwSizeNeeded);
After finish, dwSizeNeeded have 15 as value and lpServiceName have "". Where I'm wrong calling to this function? Need any special right here? The inconvenience here is that this app doesn't have admin rights so I cannot (I guess) set SC_MANAGER_ALL_ACCESS. Of course, My service is up and running in system, so I have not bad display name.
Two lines needs to be modified:
...
TCHAR lpServiceName[512];
DWORD dwSizeNeeded = sizeof lpServcieName / sizeof lpServiceName[0]; // Number of elements in buffer
...
You should also see what GetServiceKeyName returns as that is the signal if it has succeeded or not. Checking the string is only valid if GetServiceKeyName returns TRUE.

How to display absolute path with device name of currently opened file

The first two lines of this code showing file name excluding device name like /Document/temp but I want
to show also device name like L"\Device\Harddisk0\DR0\Document\temp. I am using this code to call ObQueryNameString routine but it is showing NULL.
Please tell me what is wrong with code. I think memory is not allocating
properly.
PFILE_OBJECT pFileObject = IoGetCurrentIrpStackLocation(Irp)->FileObject;
if (pFileObject)
{
DbgPrint("FileName : %wZ\n", pFileObject->FileName);
}
NTSTATUS status = STATUS_UNSUCCESSFUL;
OBJECT_NAME_INFORMATION objName = {0};
ULONG ReturnLength = 1024;
ObQueryNameString(DeviceObject, objName, sizeof(objName), ReturnLength);
DbgPrint("FileName : %wZ\n", &objName);
Have you considered using GetFullPathName function?
Refer to http://msdn.microsoft.com/en-us/library/aa364963%28VS.85%29.aspx for more accurate explanation what it does.

Using RegQueryValueEx and HKEY_PERFORMANCE_COUNTER to Get "Disk Bytes/sec%

I've looked for examples and documentation, but I still can't figure this out...
How do you use RegQueryValueEx (not the PdhXxx functions) to query for something like Disk Bytes/sec?
I've tried the following:
DWORD type;
static union { TCHAR Data[32 * 1024]; PERF_DATA_BLOCK Perf; } perf;//Stack buffer
DWORD cbData = sizeof(perf);
LSTATUS s = RegQueryValueEx(HKEY_PERFORMANCE_DATA,
_T("PhysicalDisk"), NULL, &type, (LPBYTE)&perf, &cbData);
PPERF_OBJECT_TYPE pObjType =
(PPERF_OBJECT_TYPE)((BYTE*)&perf + perf.Perf.HeaderLength);
but it just returns a header with no data. :(
You can't query for the data by name like that. Instead, you need to query by index. MSDN can help you with some code to find out the appropriate index to query. Unfortunately, you need to make the determination of which index at run-time.
For example, the following SHOULD retrieve the performance data for the processor.
LSTATUS s = RegQueryValueEx(HKEY_PERFORMANCE_DATA, _T("238"), NULL,
&type, (LPBYTE)&perf, &cbData);