According to Microsoft this function should retrieve the name of the network resource associated with a local device.
I am using an adaptation of the code on this Microsoft page, compiling in C. But even though the drives ("J:", and "X:") are mapped on my PC, this function does not return the share for either of them. Rather it results in either ERROR_NOT_CONNECTED or ERROR_CONNECTION_UNAVAIL.
Note: As a double check, to eliminate the possibility that I was bumping up against UAC, or some other access problem, I called WNetGetConnection(,,) from within MS Excel using a macro with code from this site. It worked just fine.
My exact C code implementation is below.
Any ideas?
My adaptation using ANSI C, built and run on Windows 7, (must include mpr.lib)
#include <windows.h>
#include <ansi_c.h>
LPTSTR szDeviceName[260]; //MAX_PATHNAME_LEN
DWORD dwResult, cchBuff = sizeof(szDeviceName);
void main(int argc, char *argv[])
{
// Call the WNetGetConnection function.
dwResult = WNetGetConnection(argv[1],
(LPTSTR) szDeviceName,
&cchBuff);
switch (dwResult)
{
//
// Print the connection name or process errors.
//
case NO_ERROR:
printf("Connection name: %s\n", szDeviceName);
break;
//
// The device is not a redirected device.
//
case ERROR_NOT_CONNECTED:
printf("Device %s is not connected.\n", argv[1]);
break;
//
// The device is not currently connected, but it is a persistent connection.
//
case ERROR_CONNECTION_UNAVAIL:
printf("Connection to %s is unavailable.\n", argv[1]);
break;
//
// Handle the error.
//
default:
printf("WNetGetConnection failed.\n");
}
getchar();
}
Related
Overview
I have been writing code to display menus and screens using the ncurses++ library. The desired result is to have these menus and screens output across a serial terminal interface.
Current Attempts
I can successfully do this using the base C ncurses library using calls.
if( (FDTERM = fopen("/dev/ttyS0", "r+")) != NULL )
{
if(FDTERM == NULL)
{
fprintf(stderr, "Error opening device: %s.\n", ncurses_device);
}
/* Set Screen */
MY_SCREEN = newterm(NULL, FDTERM, FDTERM);
if(MY_SCREEN != NULL)
{
/* Set the terminal */
set_term(MY_SCREEN);
}
}
and for getting this to work in c++ I wrote some intercept.c code to override what the call to ::initscr() in cursesw.cc actually calls to
#define ncurses_device "/dev/ttyS0"
NCURSES_EXPORT(WINDOW *) initscr(void)
{
WINDOW *result;
pthread_mutex_lock(&CUSTOM_LOCK);
if (!CUSTOM_INITIALIZED)
{
CUSTOM_INITIALIZED = true;
if( (FDTERM = fopen(ncurses_device, "r+")) != NULL )
{
if(FDTERM == NULL)
{
fprintf(stderr, "Error opening device: %s.\n", ncurses_device);
}
/* Set Screen */
MY_SCREEN = newterm(NULL, FDTERM, FDTERM);
if(MY_SCREEN != NULL)
{
/* Set the terminal */
set_term(MY_CDU_SCREEN);
}
/* def_shell_mode - done in newterm/_nc_setupscreen */
def_prog_mode();
}
else
{
CUSTOM_INITIALIZED = true;
NCURSES_CONST char *name;
if ((name = getenv("TERM")) == 0 || *name == '\0')
{
static char unknown_name[] = "unknown";
name = unknown_name;
}
if (newterm(name, stdout, stdin) == 0)
{
fprintf(stderr, "Error opening terminal: %s.\n", name);
result = NULL;
}
}
}
#if NCURSES_SP_FUNCS
#ifdef CURRENT_SCREEN
NCURSES_SP_NAME(def_prog_mode) (CURRENT_SCREEN);
#else
NCURSES_SP_NAME(def_prog_mode) (SP);
#endif
#else
def_prog_mode();
#endif
result = stdscr;
pthread_mutex_unlock(&CUSTOM_LOCK);
return Win(result);
}
The intercept.c allows the device as defined to be used if available. It
also allows initscr() to fall back to the default behavior of using the current terminal.
This works when used when for debugging, but I feel there has to be a better way to setup NCurses or the environment to direct NCurses output over the desired serial port.
The above solution now does not work when executing code on boot as there is not a terminal definition available.
This is being developed to support both RHEL 7 and 6. Some research seems to point to creating a new environment service using getty, agetty or by editing start-tty.conf as noted (https://unix.stackexchange.com/a/318647).
But the other issue is pointing NCurses++ to output to the correct environment. From what I have seen in NCurses source code it appears that the ::initscr() is called by default from cursesw.cc, which makes it harder to just point NCurses to a new environment.
Questions
How do I setup NCurses++ to output to a specified tty?
How to properly setup an environment for NCurses to use on system boot?
Update 1:
Updated code to do the following:
// Save the current stdin/stdout file descriptors
int saved_stdin = dup(fileno(stdin));
int saved_stdout = dup(fileno(stdout));
// Set the stdin/stdout to the desired device
freopen(ncurses_device, "w+", stdout);
freopen(ncurses_device, "r+", stdin);
// Initialize the NCursesMenu
NCursesMenu *m_pMenu = new NCursesMenu(m_pMenuItems);
// Restore the saved_stdin/stdout to the correct locations
dup2(saved_stdin, STDIN_FILENO);
dup2(saved_stdout, STDOUT_FILENO);
// Close the saved_stdin/stdout file descriptors
close(saved_stdin);
close(saved_stdout);
This allows NCurses to copy the current FILE* as defined here in newterm, but once the stdin/stdout FILE* is restored to the saved file descriptor the manipulation is lost. If the device is only pointed to the new device it works for NCurses, but all debug/test information is not visible because it is overwritten by NCurses in the current terminal.
initscr doesn't assume anything about the devices: it uses the current input/output stdin and stdout when initializing (and via newterm, setupterm, it copies the file-descriptors).
If your application (or environment/scripting) sets those streams to the device you'd like to connect to, that should be enough for the C++ interface. ncurses doesn't use the C+ cout, etc.
I am using cmake to build my project from the command line. The problem is, as soon as the executable finishes running it disappear immediately and I have mere milliseconds the contents that are printed on screen. I can't read much in milliseconds. Is there anything I can do so that the console screen doesnt disappear as soon as it has finished executing?
here is my CMakeLists.txt:
cmake_minimum_required(VERSION 2.8)
project(TotallyFree C)
add_executable(Acrolibre acrolibre.c)
set(LIBSRC acrodict.c acrodict.h)
add_library(acrodict ${LIBSRC})
add_executable(Acrodictlibre acrolibre.c)
target_link_libraries(Acrodictlibre acrodict)
set_target_properties(Acrodictlibre PROPERTIES COMPILE_FLAGS "-DUSE_ACRODICT")
and here is my equivalent of main.cpp:
//#include <windows.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#ifdef USE_ACRODICT
#include "acrodict.h"
#endif
int main(int argc, char* argv[])
{
//int waitTime = 10000000;
const char* name;
#ifdef USE_ACRODICT
const acroItem_t* item;
#endif
if(argc < 2)
{
fprintf(stderr, "%s: you need one argument\n", argv[0]);
fprintf(stderr, "%s <name>\n", argv[0]);
exit(EXIT_FAILURE);
}
name = argv[1];
#ifndef USE_ACRODICT
//if(strcasecmp(name, "toulibre")==0){
if(_stricmp(name, "toulibre")==0){
printf("Toulibre is a French organization promoting FLOSS.\n");
}
#else
item = acrodict_get(name);
if(NULL != item){
printf("%s: %s\n", item->name, item->description);
}else if(item = acrodict_get(name)){
printf("<%s> is unknown maybe you mean:\n", name);
printf("%s: %s\n", item->name, item->description);
}
#endif
else{
printf("Sorry, I don't know: <%s>\n", name);
//Sleep(waitTime);
return EXIT_FAILURE;
}
//Sleep(waitTime);
return EXIT_SUCCESS;
}
As you can see I even used Sleep() and #include to delay this shutting down of the console. But it doesn't work. Is there anything anyone can recommend?
The problem is not in the make files here. Your program exits, and the console window disappears. Try using getch() before returning from main() for the program to wait for any key before exiting. Or, you can run your program from a console.
This has nothing to do with CMake, and everything to do with the way you're running your application.
When you double-click a console EXE in Windows, it opens a new console, runs the program, and closes the console, lie it should.
You have two options:
Run the program from the command-line of an already open console (cmd.exe)
Add this code to the end of main:
printf("Press Enter to exit\n");
getchar();
I would write a program as follows
int main ()
{
FILE *fp = fopen("test.txt", "r")
if (fp == NULL)
{
printf("Sorry, file doesn't exist.");
return 0;
}
return 0;
}
Is there any other check that I would need to make sure before or after opening a file?
What if the opening of a file can damage the system(virus)? is there any check for that?
What if the file is not a .txt file, user just renamed mp3 file to a txt file?
No other check needed.
I always also make it a practice of calling fclose, however, when done with the FILE*.
The mode r should be used to open text files only. Different systems have different ways of storing text, and this mode will automatically translate the file accordingly. For instance, DOS/Windows use \r\n to represent new lines, UNIX-like systems use \n, and MAC uses \r among other possible differences.
To open and read a file truly as it is, in binary-safe mode, you should use rb.
This mode gives you full control of what you're writing to binary level, and is the only safe way to read and write binary data such as struct dumps, encrypted information etc.
after opening a file
As careful as you are when opening the file, you should as well be when reading, writing and closing it. So always check the outcome of the calls involved to do so.
I see it is an old question. However:
You may do some additional security checks to validate you are opening a real file, not a symbolic link.
Reason: replacing file by a link to another file is one of the known attack technics (related to CWE-362).
The file can be replaced by a link pointing to an engineered file containing a sequence that should hack/crash your application instead of the expected file.
So, the best practice is to add code like this:
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
/* Return: 0 if file is a regular file, -1 if not */
static int test_file_type(const char *file)
{
struct stat st;
if (0 != lstat(file, &st)) {
fprintf(stderr, "lstat failed, probably no such a file\n");
perror("lstat");
return (-1);
}
if (S_IFREG != (st.st_mode & S_IFMT)) {
fprintf(stderr, "Error on file [%s] opening: not a regular file, but ", file);
switch (st.st_mode & S_IFMT) {
case S_IFSOCK:
fprintf(stderr, "socket\n");
break;
case S_IFLNK:
fprintf(stderr, "symbolic link\n");
break;
case S_IFBLK:
fprintf(stderr, "block device\n");
break;
case S_IFDIR:
fprintf(stderr, "directory\n");
break;
case S_IFCHR:
fprintf(stderr, "character device\n");
break;
case S_IFIFO:
fprintf(stderr, "FIFO\n");
break;
}
return (-1);
}
return (0);
}
If this function return < 0, the file is not a regular file. Don't open it.
Also, read here
you might prefer using fopen_s. fopen_s is a newer variant of fopen that has a parameter for validation and hands back an error code instead of a pointer for the case if something goes wrong during the open process. It is safer than the base variant because it accounts for more edge conditions.
I hope you find it helpful!
How do I programmatically open a file in its default program in Linux (im using Ubuntu 10.10).
For example, opening *.mp3 will open the file in Movie Player (or something else).
You need to run gnome-open, kde-open, or exo-open, depending on which desktop you are using.
I believe there is a project called xdg-utils that attempts to provide a unified interface to the local desktop.
So, something like:
snprintf(s, sizeof s, "%s %s", "xdg-open", the_file);
system(s);
Beware of code injection. It's safer to bypass scripting layers with user input, so consider something like:
pid = fork();
if (pid == 0) {
execl("/usr/bin/xdg-open", "xdg-open", the_file, (char *)0);
exit(1);
}
// parent will usually wait for child here
Ubuntu 10.10 is based on GNOME. So, it would be good idea to use
g_app_info_launch_default_for_uri().
Something like this should work.
#include <stdio.h>
#include <gio/gio.h>
int main(int argc, char *argv[])
{
gboolean ret;
GError *error = NULL;
g_type_init();
ret = g_app_info_launch_default_for_uri("file:///etc/passwd",
NULL,
&error);
if (ret)
g_message("worked");
else
g_message("nop: %s", error->message);
return 0;
}
BTW, xdg-open, a shell script, tries to determin your desktop environment and call a known helper like gvfs-open for GNOME, kde-open for KDE, or something else. gvfs-open ends up calling g_app_info_launch_default_for_uri().
A simple solution with less coding:
I've tested this program on my Ubuntu and it is working fine, and if I am not wrong you are looking for something like this
#include <stdio.h>
#include <stdlib.h>
int main()
{
system("firefox file:///dox/song.mp3");
return 0;
}
It looks like this just sends a ping, but whats the point of that when you can just use ping?
/* WARNING: this is someone's attempt at writing a malware trojan. Do not
compile and *definitely* don't install. I added an exit as the
first line to avoid mishaps - msw */
int main (int argc, char *argv[])
{
exit(1);
unsigned int pid = 0;
char buffer[2];
char *args[] = {
"/bin/ping",
"-c",
"5",
NULL,
NULL
};
if (argc != 2)
return 0;
args[3] = strdup(argv[1]);
for (;;)
{
gets(buffer); /* FTW */
if (buffer[0] == 0x6e)
break;
switch (pid = fork())
{
case -1:
printf("Error Forking\n");
exit(255);
case 0:
execvp(args[0], args);
exit(1);
default:
break;
}
}
return 255;
}
It's a hack - or an attempt at a hack - to get arbitrary code run in a privileged mode. Ping needs to run SUID root to get a raw socket for an ICMP_ECHO_REQUEST and the intentional buffer overrun in gets(buffer) is intended to pass junk to ping.
I don't see how this could work in practice, but you shouldn't compile and run it.
It makes sure that ping is called with the arguments -c 5. Which is stupid, because a shell script or alias would be easier to read and faster to write.
This program basically emulates a simple shell program. A shell program is going to take the arguments of another program as input and launch that specified program in a new process. The program you have above is just hard coded for one specific program (ping in this case) and is very simple.
A shell program makes working with the operating system more user friendly by providing an interface to boot up programs.