|
Apologies for the shouting but this is important.
When answering a question please:
- Read the question carefully
- Understand that English isn't everyone's first language so be lenient of bad spelling and grammar
- If a question is poorly phrased then either ask for clarification, ignore it, or mark it down. Insults are not welcome
- If the question is inappropriate then click the 'vote to remove message' button
Insults, slap-downs and sarcasm aren't welcome. Let's work to help developers, not make them feel stupid.
cheers,
Chris Maunder
The Code Project Co-founder
Microsoft C++ MVP
|
|
|
|
|
For those new to message boards please try to follow a few simple rules when posting your question.- Choose the correct forum for your message. Posting a VB.NET question in the C++ forum will end in tears.
- Be specific! Don't ask "can someone send me the code to create an application that does 'X'. Pinpoint exactly what it is you need help with.
- Keep the subject line brief, but descriptive. eg "File Serialization problem"
- Keep the question as brief as possible. If you have to include code, include the smallest snippet of code you can.
- Be careful when including code that you haven't made a typo. Typing mistakes can become the focal point instead of the actual question you asked.
- Do not remove or empty a message if others have replied. Keep the thread intact and available for others to search and read. If your problem was answered then edit your message and add "[Solved]" to the subject line of the original post, and cast an approval vote to the one or several answers that really helped you.
- If you are posting source code with your question, place it inside <pre></pre> tags. We advise you also check the "Encode HTML tags when pasting" checkbox before pasting anything inside the PRE block, and make sure "Ignore HTML tags in this message" check box is unchecked.
- Be courteous and DON'T SHOUT. Everyone here helps because they enjoy helping others, not because it's their job.
- Please do not post links to your question in one forum from another, unrelated forum (such as the lounge). It will be deleted.
- Do not be abusive, offensive, inappropriate or harass anyone on the boards. Doing so will get you kicked off and banned. Play nice.
- If you have a school or university assignment, assume that your teacher or lecturer is also reading these forums.
- No advertising or soliciting.
- We reserve the right to move your posts to a more appropriate forum or to delete anything deemed inappropriate or illegal.
cheers,
Chris Maunder
The Code Project Co-founder
Microsoft C++ MVP
|
|
|
|
|
If I have a for loop, the program will allocate memory for an int every frame. When the for loop is done will the memory be released or will it result in garbage that piles up every frame.
int main()
{
for(int anint = 0; anint < 100; anint++)
{
}
}
|
|
|
|
|
This memory is allocated on the stack and will be "released" after the loop finishes.
|
|
|
|
|
The program knows I don’t need the integer after the loop is done, thanks.
|
|
|
|
|
|
I suspect maybe that is a bit different especially given the OP.
C, so before C++, would limit the scope to the method. C++ would have been based on the same. So if one has 3 for loops in one method with each in a block for a if statement, the compiler might or might not have limited it to the block.
What you refer to makes that explicit. The compiler thus must reuse the stack space.
The OP though is referring both the scope which is a method and, I believe, to each iteration of the for loop.
|
|
|
|
|
jschell wrote: C, so before C++, would limit the scope to the method. No, C89, C90 through until C98 had method scope.
jschell wrote: So if one has 3 for loops in one method with each in a block for a if statement, the compiler might or might not have limited it to the block.
The ISO standards are listed at the bottom of this page. Could you point out what you are referring to?
I see what you are saying now. You are describing old C89 rules. Are you an embedded C programmer? Those scope rules were changed way back in 1999.
Yeah, modern compilers don't have method scope at all anymore. Some embedded compilers still do C89
modified 7hrs 20mins ago.
|
|
|
|
|
Calin Negru wrote: the program will allocate memory for an int every frame.
No, it does not. An int is a "value type", and value types are usually allocated on the stack, not the heap. Also, in your example, the anint variable is only allocated (or "pushed" onto the stack once, upon execution of the loop initializer. The value in that stack location is changed on every iteration of the loop. Once the loop is complete, that variable is popped off the stack and will no longer exist.
Of course, all of this is a bit generalized and is not accurate in all cases. It is possible to allocate a value type on the heap, generally called "boxing".
|
|
|
|
|
I'm using the following function for years and used it under any Version of Windows since XP. It creates a systemtask with the start type set to "auto", just like it is expected to do. But under windows 11, the start type of the installed service always defaults to "manual" when being created. Any help solving this is very much appreciated. Am using VS2022 using toolset 1.41_XP (for reasons)
(already added some extra check for win 11... but still the start type defaults to manual in the newly created task)
static int manage_service(int action) {
SC_HANDLE hSCM = NULL, hService = NULL;
SERVICE_DESCRIPTION descr = { server_name };
char path[PATH_MAX + 20];
int success = 1;
GetModuleFileName(NULL, path, sizeof(path));
strncat(path, " ", sizeof(path));
strncat(path, service_magic_argument, sizeof(path));
if (IsRunAsAdministrator()) {
if ((hSCM = OpenSCManager(NULL, NULL, action == ID_INSTALL_SERVICE ?
GENERIC_WRITE : GENERIC_READ)) == NULL) {
success = 0;
show_error();
}
else if (action == ID_INSTALL_SERVICE) {
hService = CreateService(hSCM, service_name, service_name,
SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS,
SERVICE_AUTO_START, SERVICE_ERROR_NORMAL,
path, NULL, NULL, NULL, NULL, NULL);
if (hService) {
ChangeServiceConfig(hService, SERVICE_NO_CHANGE, SERVICE_AUTO_START,
SERVICE_NO_CHANGE, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
ChangeServiceConfig2(hService, SERVICE_CONFIG_DESCRIPTION, &descr);
OSVERSIONINFOEX osvi;
ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX));
osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
osvi.dwMajorVersion = 11;
if (GetVersionEx((OSVERSIONINFO*)&osvi)) {
ChangeServiceConfig(hService, SERVICE_NO_CHANGE, SERVICE_AUTO_START,
SERVICE_NO_CHANGE, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
}
}
else {
show_error();
}
}
else if (action == ID_REMOVE_SERVICE) {
if ((hService = OpenService(hSCM, service_name, DELETE)) == NULL ||
!DeleteService(hService)) {
show_error();
}
}
else if ((hService = OpenService(hSCM, service_name,
SERVICE_QUERY_STATUS)) == NULL) {
success = 0;
}
CloseServiceHandle(hService);
CloseServiceHandle(hSCM);
}
else {
if (action == ID_INSTALL_SERVICE) {
RunServiceAsAdmin('I', path, service_name);
}
else if (action == ID_REMOVE_SERVICE) {
RunServiceAsAdmin('R', path, service_name);
}
else {
if ((hSCM = OpenSCManager(NULL, NULL, GENERIC_READ)) == NULL) {
success = 0;
show_error();
}
if ((hService = OpenService(hSCM, service_name,
SERVICE_QUERY_STATUS)) == NULL) {
success = 0;
}
CloseServiceHandle(hService);
CloseServiceHandle(hSCM);
}
}
return success;
}
|
|
|
|
|
Hmmm,
Your code looks good to me. Although it would be nice if you captured the return values of ChangeServiceConfig .
I would recommend debugging this by checking the Event logs. Look for event ID 7040 in the "Service Control Manager" log source. You might need to enable auditing.
Also, try temporarily adding a Windows Defender exclusion on the service file path if your executable is unsigned/untrusted. I'm wondering if Defender is blocking the change.
|
|
|
|
|
 Just found out somethhing more.... As soon as I invoke the service creation function from within the program, I do get the normal service controll manager asking for elevated rights in order to create the service, what is exactly what happen. But then the service gets created with start type set to "manual".
If I do start the program manually "as Administrator" and then invoke the service creation function, the service gets created correctly with start type "auto". So there probably might be a problem with my elevation of rights!?... will check this. Strange though, that it works fin under any Windows version since XP... just not windows 11...
Here is the code to start with elevated rights:
BOOL IsRunAsAdministrator()
{
BOOL isRunAsAdmin = FALSE;
DWORD dwError = ERROR_SUCCESS;
PSID pAdministratorsGroup = NULL;
SID_IDENTIFIER_AUTHORITY NtAuthority = SECURITY_NT_AUTHORITY;
if (!AllocateAndInitializeSid(
&NtAuthority,
2,
SECURITY_BUILTIN_DOMAIN_RID,
DOMAIN_ALIAS_RID_ADMINS,
0, 0, 0, 0, 0, 0,
&pAdministratorsGroup))
{
goto Cleanup;
}
if (!CheckTokenMembership(NULL, pAdministratorsGroup, &isRunAsAdmin))
{
goto Cleanup;
}
Cleanup:
if (pAdministratorsGroup)
{
FreeSid(pAdministratorsGroup);
pAdministratorsGroup = NULL;
}
return isRunAsAdmin;
}
void RunServiceAsAdmin(char ch, const char *program, const char* name)
{
char param[255];
SHELLEXECUTEINFO sei = { sizeof(sei) };
memset(param, 0 , sizeof(param));
sei.lpVerb = "runas";
sei.lpFile = "sc.exe";
sei.hwnd = NULL;
sei.nShow = SW_NORMAL;
if(ch == 'I')
{
sprintf(param, "create \"%s\" binPath= \"%s\" DisplayName=\"%s\"", name, program, name);
}
else
{
sprintf(param, "delete \"%s\"", name);
}
sei.lpParameters = param;
if (!ShellExecuteEx(&sei))
{
show_error();
}
}
modified 2 days ago.
|
|
|
|
|
Well,
You appear to have a function that is checking if you are running as Administrator. Could you show me the content of that function?
|
|
|
|
|
 Here is some more complete code:
BOOL IsRunAsAdministrator()
{
BOOL isRunAsAdmin = FALSE;
DWORD dwError = ERROR_SUCCESS;
PSID pAdministratorsGroup = NULL;
SID_IDENTIFIER_AUTHORITY NtAuthority = SECURITY_NT_AUTHORITY;
if (!AllocateAndInitializeSid(
&NtAuthority,
2,
SECURITY_BUILTIN_DOMAIN_RID,
DOMAIN_ALIAS_RID_ADMINS,
0, 0, 0, 0, 0, 0,
&pAdministratorsGroup))
{
goto Cleanup;
}
if (!CheckTokenMembership(NULL, pAdministratorsGroup, &isRunAsAdmin))
{
goto Cleanup;
}
Cleanup:
if (pAdministratorsGroup)
{
FreeSid(pAdministratorsGroup);
pAdministratorsGroup = NULL;
}
return isRunAsAdmin;
}
void RunServiceAsAdmin(char ch, const char *program, const char* name)
{
char param[255];
SHELLEXECUTEINFO sei = { sizeof(sei) };
memset(param, 0 , sizeof(param));
sei.lpVerb = "runas";
sei.lpFile = "sc.exe";
sei.hwnd = NULL;
sei.nShow = SW_NORMAL;
if(ch == 'I')
{
sprintf(param, "create \"%s\" binPath= \"%s\" DisplayName=\"%s\"", name, program, name);
}
else
{
sprintf(param, "delete \"%s\"", name);
}
sei.lpParameters = param;
if (!ShellExecuteEx(&sei))
{
show_error();
}
}
static int manage_service(int action) {
SC_HANDLE hSCM = NULL, hService = NULL;
SERVICE_DESCRIPTION descr = { server_name };
char path[PATH_MAX + 20];
int success = 1;
GetModuleFileName(NULL, path, sizeof(path));
strncat(path, " ", sizeof(path));
strncat(path, service_magic_argument, sizeof(path));
if (IsRunAsAdministrator()) {
if ((hSCM = OpenSCManager(NULL, NULL, action == ID_INSTALL_SERVICE ?
GENERIC_WRITE : GENERIC_READ)) == NULL) {
success = 0;
show_error();
}
else if (action == ID_INSTALL_SERVICE) {
hService = CreateService(hSCM, service_name, service_name,
SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS,
SERVICE_AUTO_START, SERVICE_ERROR_NORMAL,
path, NULL, NULL, NULL, NULL, NULL);
if (hService) {
ChangeServiceConfig(hService, SERVICE_NO_CHANGE, SERVICE_AUTO_START,
SERVICE_NO_CHANGE, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
ChangeServiceConfig2(hService, SERVICE_CONFIG_DESCRIPTION, &descr);
OSVERSIONINFOEX osvi;
ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX));
osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
osvi.dwMajorVersion = 11;
if (GetVersionEx((OSVERSIONINFO*)&osvi)) {
ChangeServiceConfig(hService, SERVICE_NO_CHANGE, SERVICE_AUTO_START,
SERVICE_NO_CHANGE, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
}
}
else {
show_error();
}
}
else if (action == ID_REMOVE_SERVICE) {
if ((hService = OpenService(hSCM, service_name, DELETE)) == NULL ||
!DeleteService(hService)) {
show_error();
}
}
else if ((hService = OpenService(hSCM, service_name,
SERVICE_QUERY_STATUS)) == NULL) {
success = 0;
}
CloseServiceHandle(hService);
CloseServiceHandle(hSCM);
}
else {
if (action == ID_INSTALL_SERVICE) {
RunServiceAsAdmin('I', path, service_name);
}
else if (action == ID_REMOVE_SERVICE) {
RunServiceAsAdmin('R', path, service_name);
}
else {
if ((hSCM = OpenSCManager(NULL, NULL, GENERIC_READ)) == NULL) {
success = 0;
show_error();
}
if ((hService = OpenService(hSCM, service_name,
SERVICE_QUERY_STATUS)) == NULL) {
success = 0;
}
CloseServiceHandle(hService);
CloseServiceHandle(hSCM);
}
}
return success;
}
static LONG queryServiceStatus(const char* serviceName){
SC_HANDLE hSCM = NULL, hService = NULL;
SERVICE_STATUS_PROCESS ssStatus;
DWORD dwBytesNeeded;
LONG status = 0;
if ((hSCM = OpenSCManager(NULL, NULL, GENERIC_READ)) == NULL) {
show_error();
return 0;
}
hService = OpenService(
hSCM,
serviceName,
SERVICE_QUERY_STATUS);
if (hService == NULL)
{
goto END_QUERY;
}
if (!QueryServiceStatusEx(
hService,
SC_STATUS_PROCESS_INFO,
(LPBYTE) &ssStatus,
sizeof(SERVICE_STATUS_PROCESS),
&dwBytesNeeded ) )
{
goto END_QUERY;
}
if(ssStatus.dwCurrentState == SERVICE_RUNNING)
{
status = SERVICE_RUNNING;
goto END_QUERY;
}
modified 2 days ago.
|
|
|
|
|
I do see a bug.
SHELLEXECUTEINFO sei = { sizeof(sei) };
You should zero that struct out. Then set the cbSize member. Not sure if this is causing your problem though.
I'm on my TV right now so reviewing on my couch. But don't see any other issues.
|
|
|
|
|
Thanks for the tip!
Am also currently looking into a way to use the ControlService utility via CreateProcess to install the service, instead of calling CreateService directly... But not sure if I can pull that off correctly...
|
|
|
|
|
I just noticed in your original post:
Rick R. 2023 wrote:
Am using VS2022 using toolset 1.41_XP
Do you get the same behavior if you compile for Windows 11?
|
|
|
|
|
Starting to suspect the toolset, too.
Have to fix a bunch of linker problems caused by my old and pretty messy project settings, in order to test with a newer version... might take a while.
|
|
|
|
|
Well,
Alot of members check the forums everyday. Sometimes it just helps to have a few other eyes look at the issue.
Rick R. 2023 wrote: Have to fix a bunch of linker problems
XP to Win11 is a big jump, I can imagine. 
|
|
|
|
|
how to create a fingerprint sensor code with c++ from scratch
|
|
|
|
|
Probably you mean 'how to create from scratch a C++ application interfacing a fingerprint sensor module (directly handling the fingerprint sensor would be far more difficult, I suppose).
If I got you then you should carefully read the documentation of the module and implement yourself the appropriate communication code.
You may also have a look at existing libraries source code (e.g. Arduino).
"In testa che avete, Signor di Ceprano?"
-- Rigoletto
|
|
|
|
|
Hi there, I can't understand why my char type array isn't displayed with printf using string specifier %s. Here is my code.
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#define SIZE 10
void findbinary(int number, char result[], int index);
int main (void)
{
int someNumber = 233;
char result[SIZE];
int index = 0;
size_t i;
findbinary(someNumber, result,0);
printf("Decimal %d in binary = %c ",someNumber);
for(i = 0; result[i] != '\0'; i++)
printf("%s",result[i]);
}
void findbinary(int number, char result[], int index)
{
if(number == 0){
return;
}
result[index] = number % 2;
findbinary(number / 2, result, index + 1);
}
It displayed properly if I use %d specifier, but... this is char array..?
Thank you.
modified 5 days ago.
|
|
|
|
|
In:
printf("%s",result[i]) result[i] is a char not a string. It should be printed with '%c' not '%s'.
Also in:
printf("Decimal %d in binary = %c ",someNumber); you have 2 format specifiers (%d and %c) and only one argument. All hell can break loose when program accesses nonexistent argument.
Mircea
|
|
|
|
|
Your compiler will warn you about issues with printf formats not agreeing with the arguments provided. MS C seems to do this even without any additional warning flags. If you're using GCC (linux) or clang (Apple?) then you can add -Wall to the command line. The -Wall flag will generate warnings for the most often occurring code issues that are usually the cause of bugs. It's probably a good idea to add -Wextra to the command line, too.
Keep Calm and Carry On
|
|
|
|
|
Probably you meant something similar to
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#define SIZE 10
void findbinary(int number, char result[], int index);
int main (void)
{
int someNumber = 233;
char result[SIZE];
findbinary(someNumber, result,0);
printf("Decimal %d in reversed binary %s\n", someNumber, result);
return 0;
}
void findbinary(int number, char result[], int index)
{
if ( index == SIZE)
exit(-1);
if(number == 0){
result[index] = '\0'; return;
}
result[index] = (number % 2) + '0'; findbinary(number / 2, result, index + 1);
}
Note you are representing the binary number 'reversed' (that is leftmost bit is the least significant).
"In testa che avete, Signor di Ceprano?"
-- Rigoletto
|
|
|
|
|