How to create shortcut with Win32 API and c language - c

I want to write a program to create a shortcut for a specific file by using win32 API in c. my IDE is visual studio 2010.
I found this page but its sample just not compile and return many errors.
I also find this code but this always create a link with Target: "D:\Desktop\㩣睜湩潤獷湜瑯灥摡攮數" and I don't know why.
can someone tell me why the sample code of Microsoft is not working or the second one return something in Chinese shape language and also with wrong and constant location for any argument?
This is my code for MSDN sample:
#include "stdafx.h"
#include "windows.h"
#include "winnls.h"
#include "shobjidl.h"
#include "objbase.h"
#include "objidl.h"
#include "shlguid.h"
void _tmain(int argc, TCHAR *argv[])
{
CreateLink(argv[1],__argv[2],argv[3]);
}
HRESULT CreateLink(LPCWSTR lpszPathObj, LPCSTR lpszPathLink, LPCWSTR lpszDesc)
{
HRESULT hres;
IShellLink* psl;
// Get a pointer to the IShellLink interface. It is assumed that CoInitialize
// has already been called.
hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink, (LPVOID*)&psl);
if (SUCCEEDED(hres))
{
IPersistFile* ppf;
// Set the path to the shortcut target and add the description.
psl->SetPath(lpszPathObj);
psl->SetDescription(lpszDesc);
// Query IShellLink for the IPersistFile interface, used for saving the
// shortcut in persistent storage.
hres = psl->QueryInterface(IID_IPersistFile, (LPVOID*)&ppf);
if (SUCCEEDED(hres))
{
WCHAR wsz[MAX_PATH];
// Ensure that the string is Unicode.
MultiByteToWideChar(CP_ACP, 0, lpszPathLink, -1, wsz, MAX_PATH);
// Add code here to check return value from MultiByteWideChar
// for success.
// Save the link by calling IPersistFile::Save.
hres = ppf->Save(wsz, TRUE);
ppf->Release();
}
psl->Release();
}
return hres;
}
and the errors are:
1 error C1083: Cannot open include file: 'stdafx.h' and
2 IntelliSense: cannot open source file "stdafx.h"

CreateLink(argv[1],__argv[2],argv[3]);
This call looks weird. You are using argv[] for two LPCWSTR (const wchar_t *) parameters, but are using __argv[] for an LPCSTR (const char *) parameter. You should change the 2nd parameter to LPCWSTR to match the other parameters, and then use argv[] instead of __argv[].
The TCHAR-based IShellLink works with LP(C)WSTR string parameters, and LP(C)TSTR is LP(C)WSTR when compiling for Unicode. Which you are obviously doing, given that you are passing TCHAR-based argv[] values to LPCWSTR parameters, which will only compile if TCHAR is wchar_t.
IPersistFile::Save() takes only a Unicode string as input, regardless of what TCHAR maps to. You are converting the char* value from __argv[] from ANSI to Unicode, so you may as well just get a Unicode string from argv[] to begin with, and omit the call to MultiByteToWideChar() altogether.
There is no good reason to mix ANSI and Unicode strings like this. This is something the MSDN example is getting wrong.
And since your function parameters are working with Unicode strings, you should use the IShellLinkW interface directly instead of the TCHAR-based IShellLink interface.
Try this:
#include "stdafx.h"
#include "windows.h"
#include "shobjidl.h"
#include "objbase.h"
#include "objidl.h"
#include "shlguid.h"
HRESULT CreateLink(LPCWSTR lpszPathObj, LPCWSTR lpszPathLink, LPCWSTR lpszDesc)
{
HRESULT hres;
IShellLinkW* psl;
// Get a pointer to the IShellLink interface. It is assumed that CoInitialize
// has already been called.
hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLinkW, (LPVOID*)&psl);
if (SUCCEEDED(hres))
{
IPersistFile* ppf;
// Set the path to the shortcut target and add the description.
psl->SetPath(lpszPathObj);
psl->SetDescription(lpszDesc);
// Query IShellLink for the IPersistFile interface, used for saving the
// shortcut in persistent storage.
hres = psl->QueryInterface(IID_IPersistFile, (LPVOID*)&ppf);
if (SUCCEEDED(hres))
{
// Save the link by calling IPersistFile::Save.
hres = ppf->Save(lpszPathLink, TRUE);
ppf->Release();
}
psl->Release();
}
return hres;
}
void _tmain(int argc, TCHAR *argv[])
{
if (argc > 3)
CreateLink(argv[1], argv[2], argv[3]);
}

Visual Studio generates stdafx.h and stdafx.cpp when you are using new project wizard. If Create empty project checkmark is marked, it will not generate them. These files are used to build a precompiled header file Projname.pch and a precompiled types file Stdafx.obj
For small projects you can eventually remove #include "stdafx.h", but it would be better to create new project with Create empty project unmarked.

Related

winapi create shortcut failed

I want to create shortcut of a file. I found this Microsoft page that describe how to write this, and I copy that in my code to use.
But I have some problems, first it had the following error: "CoInitialize has not been called." I add this CoInitialize(nullptr); to solve the error, but I have error yet.
when I debug it, it has "Information not available, no symbols loaded for windows.storage.dll" error on this line:
hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink, (LPVOID*)&psl);
and after execution when I see the destination path, it creates a shortcut with the name but i can't open it, and it hasn't any content.
What wrong with this?
Does the error make this problem?
I'm using VS 2012.
Code Edited:
// #include "stdafx.h"
#include "windows.h"
#include "shobjidl.h"
#include <iostream>
#include <shlwapi.h>
#include "objbase.h"
#include "objidl.h"
#include "shlguid.h"
HRESULT CreateLink(LPCWSTR, LPCWSTR, LPCWSTR);
void wmain(int argc, wchar_t* argv[ ], wchar_t* envp[ ])
{
WCHAR lpwSource[MAX_PATH] = {0};
lstrcpyW(lpwSource, (LPCWSTR)argv[1]);
WCHAR lpwDest[MAX_PATH] = {0};
lstrcpyW(lpwDest, (LPCWSTR)argv[2]);
HRESULT hResult = 0;
hResult = CreateLink(lpwSource, lpwDest, NULL);
if (hResult == S_OK) {
printf("Shortcut was created successfully.\n");
} else {
printf("Shortcut creation failed.\n");
}
getchar();
}
HRESULT CreateLink(LPCWSTR lpszPathObj, LPCWSTR lpszPathLink, LPCWSTR lpszDesc)
{
HRESULT hres = 0;
IShellLink* psl;
HRESULT hCoInit = 0;
hCoInit = CoInitialize(nullptr);
// Get a pointer to the IShellLink interface. It is assumed that CoInitialize
// has already been called.
hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink, (LPVOID*)&psl);
if (SUCCEEDED(hres)) {
IPersistFile* ppf;
// Set the path to the shortcut target and add the description.
psl->SetPath(lpszPathObj);
psl->SetDescription(lpszDesc);
// Query IShellLink for the IPersistFile interface, used for saving the
// shortcut in persistent storage.
hres = psl->QueryInterface(IID_IPersistFile, (LPVOID*)&ppf);
if (SUCCEEDED(hres)) {
// Save the link by calling IPersistFile::Save.
hres = ppf->Save(lpszPathLink, TRUE);
ppf->Release();
}
psl->Release();
}
return hres;
}
As I specified in my comment, I've built the code (previous version (Question VERSION #2.) from the one at answer time - which BTW was containing some string conversions that would have most likely failed on non English locales) with VStudio 2013 and ran it on my Win 10 (English) machine. It created a valid shortcut.
So, there was nothing wrong with the code (in the sense that it wouldn't work). The problem was that the output file was also having the .png extension, and when opening it, Win would attempt to use the default image viewer / editor, which would treat the file as PNG (based on its extension). That is obviously wrong, as .lnk files have their own format (as I briefly explained in [SO]: What is the internal structure of a Windows shortcut? (#CristiFati's answer)).
The solution was to properly name the shortcut (let it have the .lnk extension).
Some additional (non critical) notes about the code (current state):
No need for C++ (11) features (nullptr (also check next bullet)):
HRESULT hCoInit = CoInitialize(NULL);
Reorganize the #includes. Use the following list:
#include <windows.h>
#include <shobjidl.h>
#include <shlguid.h>
#include <stdio.h>

GetAppliedGPOList and pGuidExtension value

I'm trying to use the GetAppliedGPOList function, but cannot find/understand what the pGuidExtension should be.
Here's the simple code so far:
#include <Windows.h>
#include <UserEnv.h>
int wmain(int argc, WCHAR *argv[])
{
//GetAppliedGPOList
DWORD flags = GPO_LIST_FLAG_MACHINE;
LPCWSTR machineName = NULL; //Local computer is used
PSID sidUser = NULL;
GUID *pGuidExtension; //What is the GUID of the extension?
PGROUP_POLICY_OBJECT *ppGPOList;
return 0;
}
Cannot run the function because I need to send that value.
Any example about the pGuidExtension value?
I did search here but found nothing about it.
Thank you.
The guids is listed at
HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon\GPExtensions
For example - Group Policy Client Side Extension List. The GetAppliedGPOList is looked under
HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Group Policy\History\{GuidExtension}
key

Use a dynamic library dll in C program

I want to use a dll-file in my C-Code, but are very confused about the syntax.
My Story: I made a simple function in Matlab ( f(x1,x2)=x1*x2 ), with the "Matlab Coder" I translated it to C-Code and generated an exe, I could run it from the terminal with arguments.Now I generated a dll instead of an exe and want to use the dll.
Since now I could not make Code explanations, I googled, make work for me. I look up Syntax in http://en.cppreference.com/w/ but for my surprise there wasn't even an entry for e.g. GetProcAddress or LoadLirbary.
Here is the C-Code in which I would like to use the dll:
#include <stdio.h>
#include <stdlib.h>
/*
* In my dream I would load the dll function here
* with something like Load(mytimes4.dll)
*/
int main(int argc, char *argv[]) {
double x1,x2,myresult;
//Load Arguments from Terminal
sscanf(argv[1], "%lf", &x1);
sscanf(argv[2], "%lf", &x2);
// Use and print the function from mytimes4.dll
myresult = mytimes4(x1,x2);
printf("%3.2f\n",myresult);
return 0;
}
After generating the dll, Matlab gave me the following folder:
"dll-folder" produced by Matlab
Can someone give me a most simple but complete Code that would work with my example? What files are needed (maybe .def or .exp)? Also for Explanations of the lines involved using the dll I would be gratefull. Or if not, you maybe have some background knowledge that makes the complex syntax reasonable.Thanks in advance!
System information: Windows 7 Pro 64, Matlab 64 2016b, gcc cygwin 64, eclipse ide.
With the link of thurizas I could solve my problem.
https://msdn.microsoft.com/en-us/library/windows/desktop/ms686944(v=vs.85).aspx
I copied the code from the side. Below you can see the code with additional comments of mine and with ,in my opinion, more clearly naming. Thus it is probably easier to use for beginners as I am.
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
/*Declaration of the function,contained in dll, as pointer with the arbitrary pointer name
"*MYFUNCTIONPOINTER" (not sure if it has to be in big letters).
In my case the function means simply f(x1,x2) = x1*x2 and is thus as double declared*/
typedef double (*MYFUNCTIONPOINTER)(double, double);
int main() {
HINSTANCE hinstLib;
//"myfunction" is the arbitrary name the function will be called later
MYFUNCTIONPOINTER myfunction;
BOOL fFreeResult, fRunTimeLinkSuccess = FALSE;
//Tell the dll file
hinstLib = LoadLibrary(TEXT("mypersonal.dll"));
if (hinstLib != NULL)
{
/* At this line "myfunction" gets its definition from "MYFUNCTIONPOINTER"
and can be used as any other function.The relevant function in the dll has
to be told here.*/
myfunction = (MYFUNCTIONPOINTER) GetProcAddress(hinstLib, "mydllfunction");
// If the function address is valid, call the function.
if (NULL != myfunction)
{
fRunTimeLinkSuccess = TRUE;
// The function can be used.
double myoutput;
myoutput = myfunction(5,7);
printf("%f\n",myoutput);
getchar();
}
// Free the DLL module.
fFreeResult = FreeLibrary(hinstLib);
}
// If unable to call the DLL function, use an alternative.
if (! fRunTimeLinkSuccess)
printf("Message printed from executable\n");
return 0;
}

libharu memory allocation failed while loading image

I have some C code trying to use libharu. Although I can use every function of this library (even UTF8) I can hardly draw images. Here is some very basic code:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <setjmp.h>
#include "hpdf.h"
jmp_buf env;
#ifdef HPDF_DLL
void __stdcall
#else
void
#endif
error_handler (HPDF_STATUS error_no,
HPDF_STATUS detail_no,
void *user_data)
{
printf ("ERROR: error_no=%04X, detail_no=%u\n", (HPDF_UINT)error_no,
(HPDF_UINT)detail_no);
longjmp(env, 1);
}
int main (int argc, char **argv)
{
HPDF_Doc pdf;
HPDF_Font font;
HPDF_Page page;
char fname[256];
HPDF_Image image;
strcpy (fname, argv[0]);
strcat (fname, ".pdf");
pdf = HPDF_New (error_handler, NULL);
if (!pdf) {
printf ("error: cannot create PdfDoc object\n");
return 1;
}
/* error-handler */
if (setjmp(env)) {
HPDF_Free (pdf);
return 1;
}
font = HPDF_GetFont (pdf, "Helvetica", NULL);
page = HPDF_AddPage (pdf);
HPDF_Page_SetWidth (page, 550);
HPDF_Page_SetHeight (page, 500);
image = HPDF_LoadPngImageFromFile (pdf, "img.png");
HPDF_SaveToFile (pdf, fname);
HPDF_Free (pdf);
return 0;
}
When I compile this I have ERROR: error_no=1015, detail_no=0. I have found a similar post in stackoverflow: this. However although original poster said the problem is solved it hardly helped mine. I moved img.png to a folder and recompiled the file. Changed the code that says /home/name/path/to/img.png which is the direct path to image. Nothing works. I "always" have the same error, but when I change the name of file I have ERROR: error_no=1017, detail_no=2 which basicly means program cannot find image (according to reference of libharu) So I deduce that program finds img.png; but, it's strange but, cannot allocate the necessary memory. Which is weird because I cannot see any reason for this program not to allocate memory. I have every kind of permission.
I am using GCC 4.7.2 under Ubuntu Quantal Quetzal and libharu 2.3.0 RC2. Thank you for your help.
Hello Equalities of polynomials .
I also encountered the same problem when i integrated the haru sdk in my macOS environment.
The error_handler returned ERROR: error_no=1017, detail_no=2,and then i checked the official document for haru at http://libharu.sourceforge.net/error_handling.html query 0x1017 indicates that the file failed to open, so i suspect that the second parameter of the HPDF_LoadPngImageFromFile method needs to pass an exact png image file path, so after I modified it, the problem was solved, and I hope to help you.
code ad follow:
char filename1[255];
strcpy(filename1, "/Users/xx/Downloads/lusaceg.com.png");
image = HPDF_LoadPngImageFromFile (pdf, filename1);
Faithfully yours.

How to obtain data from WMI using a C Application?

I have a pure C application that issues IOCTL calls to my adapter driver and displays info ,this is however compiled using Visual Developer Studio 5(non-managed code) ... I need to get some info however from my adapter using WMI .... My googling efforts show that i would need to write a C++ Application using COM to achieve any form of communication with wMI or a C# with .NET app
a) Is that really the case? NO work around for my C application?
b) If above is true,what are the minimum level changes that i would need to do my project/wp /workspace settings?
Thanks
Som
You can invoke COM from C. The syntax is somewhat less friendly than that of C++, but it works. COM was initially designed to work from either C or C++, and native C language support is included in COM and WMI header files. It will be long though... your program will be responsible for allocating all the necessary objects, checking for error conditions from each and every COM call, and for releasing the objects it instantiated.
When using documentation written with C++ in mind, convert COM calls of the form:
pSomething->Method(arg1, ...); // C++
to:
pSomething->lpVtbl->Method(pSomething, arg1, ...); // C
Below is the shortest piece of C code I could get to actually pull some information from WMI. If successful, it should list the processors on your computer, along with their clock frequency in MHz. The program takes care of disposing resources it allocates, but it does no error checking whatsoever (you should look at those hr values before continuing each step).
This is a visual studio 2008 "Win32 Console Application" with the main file renamed to a .c extension, and the extra stdafx files removed. To get the program to link, make sure to include wbemuuid.lib in the project properties, under Configuration Properties/Linker/Input/Additional Dependencies. It ran successfully on my Vista box.
#define _WIN32_WINNT 0x0400
#define _WIN32_DCOM
#include <stdio.h>
#include <tchar.h>
#include <windows.h>
#include <wbemidl.h>
void _tmain(int argc, _TCHAR* argv[])
{
// result code from COM calls
HRESULT hr = 0;
// COM interface pointers
IWbemLocator *locator = NULL;
IWbemServices *services = NULL;
IEnumWbemClassObject *results = NULL;
// BSTR strings we'll use (http://msdn.microsoft.com/en-us/library/ms221069.aspx)
BSTR resource = SysAllocString(L"ROOT\\CIMV2");
BSTR language = SysAllocString(L"WQL");
BSTR query = SysAllocString(L"SELECT * FROM Win32_Processor");
// initialize COM
hr = CoInitializeEx(0, COINIT_MULTITHREADED);
hr = CoInitializeSecurity(NULL, -1, NULL, NULL, RPC_C_AUTHN_LEVEL_DEFAULT, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE, NULL);
// connect to WMI
hr = CoCreateInstance(&CLSID_WbemLocator, 0, CLSCTX_INPROC_SERVER, &IID_IWbemLocator, (LPVOID *) &locator);
hr = locator->lpVtbl->ConnectServer(locator, resource, NULL, NULL, NULL, 0, NULL, NULL, &services);
// issue a WMI query
hr = services->lpVtbl->ExecQuery(services, language, query, WBEM_FLAG_BIDIRECTIONAL, NULL, &results);
// list the query results
if (results != NULL) {
IWbemClassObject *result = NULL;
ULONG returnedCount = 0;
// enumerate the retrieved objects
while((hr = results->lpVtbl->Next(results, WBEM_INFINITE, 1, &result, &returnedCount)) == S_OK) {
VARIANT name;
VARIANT speed;
// obtain the desired properties of the next result and print them out
hr = result->lpVtbl->Get(result, L"Name", 0, &name, 0, 0);
hr = result->lpVtbl->Get(result, L"MaxClockSpeed", 0, &speed, 0, 0);
wprintf(L"%s, %dMHz\r\n", name.bstrVal, speed.intVal);
// release the current result object
result->lpVtbl->Release(result);
}
}
// release WMI COM interfaces
results->lpVtbl->Release(results);
services->lpVtbl->Release(services);
locator->lpVtbl->Release(locator);
// unwind everything else we've allocated
CoUninitialize();
SysFreeString(query);
SysFreeString(language);
SysFreeString(resource);
}
Another option, if you want to keep the impact to your existing C application low, is to write a DLL that internally can use C++ and COM wrapper classes to query the desired WMI information.
This DLL can provide a plain C interface to adapt to your application. Thats the way I would go for.

Resources