Home > database >  Why Visual Studio gives me errors but compiling with cl.exe works fine?
Why Visual Studio gives me errors but compiling with cl.exe works fine?

Time:10-09

I have a piece of c code main.c.

#define STRICT

#ifndef UNICODE
#define T_MAX_PATH MAX_PATH
#else
#define T_MAX_PATH 32767
#endif

#include <tchar.h>

#include <windows.h>

#include <windowsx.h>
#include <shlobj.h>
#include <shlwapi.h>
#include <commdlg.h>

// tcc, any other compiler support wWinMain() and '__argc/__targv'
//shlguid.h
DEFINE_GUID(IID_IDropTarget, 0x00000122, 0x0000, 0x0000, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46);
DEFINE_GUID(IID_IDataObject, 0x0000010e, 0x0000, 0x0000, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46);

//
#define WINGDIPAPI __stdcall
#define GDIPCONST const

typedef enum GpStatus {
    Ok = 0,
    GenericError = 1,
    InvalidParameter = 2,
    OutOfMemory = 3,
    ObjectBusy = 4,
    InsufficientBuffer = 5,
    NotImplemented = 6,
    Win32Error = 7,
    WrongState = 8,
    Aborted = 9,
    FileNotFound = 10,
    ValueOverflow = 11,
    AccessDenied = 12,
    UnknownImageFormat = 13,
    FontFamilyNotFound = 14,
    FontStyleNotFound = 15,
    NotTrueTypeFont = 16,
    UnsupportedGdiplusVersion = 17,
    GdiplusNotInitialized = 18,
    PropertyNotFound = 19,
    PropertyNotSupported = 20,
    ProfileNotFound = 21
} GpStatus;

typedef DWORD ARGB;
typedef void GpBitmap;
typedef void* DebugEventProc;
typedef GpStatus(WINGDIPAPI* NotificationHookProc)(ULONG_PTR* token);
typedef VOID(WINGDIPAPI* NotificationUnhookProc)(ULONG_PTR token);

typedef struct GdiplusStartupInput {
    UINT32 GdiplusVersion;
    DebugEventProc DebugEventCallback;
    BOOL SuppressBackgroundThread;
    BOOL SuppressExternalCodecs;
} GdiplusStartupInput;

typedef struct GdiplusStartupOutput {
    NotificationHookProc NotificationHook;
    NotificationUnhookProc NotificationUnhook;
} GdiplusStartupOutput;

GpStatus WINGDIPAPI GdiplusStartup(ULONG_PTR*, GDIPCONST GdiplusStartupInput*, GdiplusStartupOutput*);
VOID WINGDIPAPI GdiplusShutdown(ULONG_PTR);

GpStatus WINGDIPAPI
GdipCreateBitmapFromHICON(HICON hicon, GpBitmap** bitmap);

GpStatus WINGDIPAPI
GdipCreateHBITMAPFromBitmap(GpBitmap* bitmap, HBITMAP* hbmReturn, ARGB background);

VOID WINGDIPAPI GdipFree(VOID*);

#define IDM_SENDTOFIRST 0

TCHAR* FOLDER_SENDTO;
UINT    idm_g = IDM_SENDTOFIRST;
TCHAR** PSENDTO;                      /* store the shourtcuts full path */
//
HBITMAP* hBmpImageA;                    /* MenuItemBitmap */

HINSTANCE       g_hinst;                /* My hinstance */
HMENU           g_hmenuSendTo;          /* Our SendTo popup */
LPSHELLFOLDER   g_psfDesktop;           /* The desktop folder */

UINT FORKING = 0;   /* compatible with UAC focus changes */

LPSHELLFOLDER PIDL2PSF(LPITEMIDLIST pidl)
{
    LPSHELLFOLDER psf = NULL;

    if (pidl) {
        g_psfDesktop->lpVtbl->BindToObject(g_psfDesktop, pidl, NULL, &IID_IShellFolder, (LPVOID*)&psf);
        // failed: got NULL
    }
    return psf;
}

LPITEMIDLIST PidlFromPath(HWND hwnd, LPCTSTR pszPath)
{
    LPITEMIDLIST pidl;
    ULONG ulEaten;
    DWORD dwAttributes;
    HRESULT hres;
    WCHAR* wszName;
    //
    wszName = calloc(T_MAX_PATH   1, sizeof(WCHAR));
#ifdef UNICODE
    if (wcslen(pszPath) >= T_MAX_PATH) { return NULL; }
    wcscpy(wszName, pszPath);
#else
    if (!MultiByteToWideChar(CP_ACP, 0, pszPath, -1, wszName, T_MAX_PATH)) {
        return NULL;
    }
#endif
    hres = g_psfDesktop->lpVtbl->ParseDisplayName(g_psfDesktop, hwnd, NULL, wszName, &ulEaten, &pidl, &dwAttributes);
    free(wszName);
    if (FAILED(hres)) {
        return NULL;
    }

    return pidl;
}

LPSHELLFOLDER GetFolder(HWND hwnd, LPCTSTR pszPath)
{
    LPITEMIDLIST pidl;

    pidl = PidlFromPath(hwnd, pszPath);

    return PIDL2PSF(pidl);
}

/*****************************************************************************
 *  GetUIObjectOfAbsPidl
 *      Given an absolute (desktop-relative) LPITEMIDLIST, get the
 *      specified UI object.
 *****************************************************************************/
HRESULT GetUIObjectOfAbsPidls(HWND hwnd, LPITEMIDLIST* pidls, INT NumOfpidls, REFIID riid, LPVOID* ppvOut)
{
    LPITEMIDLIST* pidlLasts;
    LPSHELLFOLDER psf;
    HRESULT hres;
    INT i;

    /* Just for safety's sake. */
    *ppvOut = NULL;

    pidlLasts = malloc(sizeof(LPITEMIDLIST) * NumOfpidls);
    if (pidlLasts == NULL) return E_FAIL;

    for (i = 0; i < NumOfpidls; i  ) {
        hres = SHBindToParent(pidls[i], &IID_IShellFolder, (LPVOID*)&psf, (LPCITEMIDLIST*)&pidlLasts[i]);
        if (FAILED(hres)) goto Fail;
        if (i < NumOfpidls - 1) psf->lpVtbl->Release(psf);
    }

    /* Now ask the parent for the the UI object of the child. */
    hres = psf->lpVtbl->GetUIObjectOf(psf, hwnd, NumOfpidls, pidlLasts, riid, NULL, ppvOut);

    /*
     *  Regardless of whether or not the GetUIObjectOf succeeded,
     *  we have no further use for the parent folder.
     */
Fail:
    psf->lpVtbl->Release(psf);

    return hres;
}

HRESULT GetUIObjectOfPaths(HWND hwnd, LPCTSTR* pszPaths, INT NumOfPaths, REFIID riid, LPVOID* ppvOut)
{
    LPITEMIDLIST* pidls;
    HRESULT hres;
    INT i;

    /* Just for safety's sake. */
    *ppvOut = NULL;

    pidls = calloc(NumOfPaths, sizeof(LPITEMIDLIST));
    if (pidls == NULL) return E_FAIL;

    for (i = 0; i < NumOfPaths; i  ) {
        pidls[i] = PidlFromPath(hwnd, pszPaths[i]);
        if (pidls[i] == NULL) goto Fail;
    }

    hres = GetUIObjectOfAbsPidls(hwnd, pidls, NumOfPaths, riid, ppvOut);

Fail:
    for (i = 0; i < NumOfPaths; i  ) {
        CoTaskMemFree(pidls[i]);
    }
    free(pidls);

    return hres;
}

/*****************************************************************************
 *  DoDrop
 *      Drop a data object on a drop target.
 *****************************************************************************/
void DoDrop(LPDATAOBJECT pdto, LPDROPTARGET pdt)
{
    POINTL pt = { 0, 0 };
    DWORD dwEffect;
    HRESULT hres;

    dwEffect = DROPEFFECT_COPY | DROPEFFECT_MOVE | DROPEFFECT_LINK;
    hres = pdt->lpVtbl->DragEnter(pdt, pdto, MK_LBUTTON, pt, &dwEffect);
    if (SUCCEEDED(hres) && dwEffect) {
        hres = pdt->lpVtbl->Drop(pdt, pdto, MK_LBUTTON, pt, &dwEffect);

    }
    else {
        hres = pdt->lpVtbl->DragLeave(pdt);
    }
}

LPTSTR pidl_to_name(LPSHELLFOLDER psf, LPITEMIDLIST pidl, SHGDNF uFlags) {
    HRESULT hres;
    STRRET str;
    LPTSTR pszName = NULL;
    //
    hres = psf->lpVtbl->GetDisplayNameOf(psf, pidl, uFlags, &str);
    if (hres == S_OK) {
        hres = StrRetToStr(&str, pidl, &pszName);
    }
    return pszName;
}

BOOL GethBitMapByPath(LPTSTR pszPath, HBITMAP* phbmp) {
    SHFILEINFO ShFI = { 0 };
    BOOL hasBmpImage = FALSE;
    //
    if (SUCCEEDED(SHGetFileInfo(pszPath, FILE_ATTRIBUTE_NORMAL, &ShFI, sizeof(SHFILEINFO), SHGFI_ICON | SHGFI_SMALLICON | SHGFI_USEFILEATTRIBUTES))) {
        GpBitmap* bitmap = NULL;
        if (GdipCreateBitmapFromHICON(ShFI.hIcon, &bitmap) == Ok) {
            hasBmpImage = !(GdipCreateHBITMAPFromBitmap(bitmap, phbmp, 0));
            GdipFree(bitmap);
        }
        DestroyIcon(ShFI.hIcon);
    }
    //
    return hasBmpImage;
}

void FolderToMenu(HWND hwnd, HMENU hmenu, LPCTSTR pszFolder)
{
    LPSHELLFOLDER psf;
    HRESULT hres;
    STRRET str;

    /* OS_WOW6432 */
    if ((PROC)(GetProcAddress(GetModuleHandle(_T("Shlwapi")), (LPCSTR)437))(30)) {
        AppendMenu(hmenu, MF_GRAYED | MF_DISABLED | MF_STRING, idm_g, TEXT("64-bit OS needs 64-bit version :p"));
        return;
    }

    psf = GetFolder(hwnd, pszFolder);
    if (psf) {
        LPENUMIDLIST peidl;
        hres = psf->lpVtbl->EnumObjects(psf, hwnd,
            SHCONTF_FOLDERS | SHCONTF_NONFOLDERS,
            &peidl);
        if (SUCCEEDED(hres)) {
            LPITEMIDLIST pidl;
            MENUITEMINFO mii;
            MENUINFO mi;
            BOOL hasBmpImage;
            while (peidl->lpVtbl->Next(peidl, 1, &pidl, NULL) == S_OK) {
                LPTSTR pszPath, pszName;
                //
                pszPath = pidl_to_name(psf, pidl, SHGDN_FORPARSING);
                if (pszPath == NULL) { continue; }
                pszName = pidl_to_name(psf, pidl, SHGDN_NORMAL);
                if (pszName == NULL) { continue; }
                //
                // path should be enough
                CoTaskMemFree(pidl);
                //
                // store path rather than retrial, as we check if it is dir.
                PSENDTO = (TCHAR**)realloc(PSENDTO, sizeof(TCHAR*) * (idm_g - IDM_SENDTOFIRST   1));
                if (PSENDTO == NULL) { continue; }
                PSENDTO[idm_g] = _tcsdup(pszPath);
                //
                hBmpImageA = (HBITMAP*)realloc(hBmpImageA, sizeof(HBITMAP*) * (idm_g - IDM_SENDTOFIRST   1));
                hasBmpImage = GethBitMapByPath(pszPath, &hBmpImageA[idm_g]);
                //
                if (PathIsDirectory(pszPath)) {
                    HMENU hSubMenu = CreatePopupMenu();
                    if (AppendMenu(hmenu, MF_ENABLED | MF_POPUP | MF_STRING, (UINT)hSubMenu, pszName)) {
                        mi.cbSize = sizeof(mi);
                        mi.fMask = MIM_HELPID;
                        mi.dwContextHelpID = idm_g;
                        SetMenuInfo(hSubMenu, &mi);
                        idm_g  ;
                        //FolderToMenu(hwnd, hSubMenu, pszPath);
                    }
                }
                else {
                    if (AppendMenu(hmenu, MF_ENABLED | MF_STRING, idm_g, pszName)) {
                        mii.cbSize = sizeof(mii);
                        mii.fMask = MIIM_DATA;
                        //mii.dwItemData = (ULONG_PTR)pidl;
                        if (hasBmpImage) {
                            mii.fMask |= MIIM_BITMAP;
                            mii.hbmpItem = hBmpImageA[idm_g];
                        }
                        SetMenuItemInfo(hmenu, idm_g, FALSE, &mii);
                        idm_g  ;
                    }
                }
                //
                CoTaskMemFree(pszPath);
                CoTaskMemFree(pszName);
            }
            peidl->lpVtbl->Release(peidl);
        }
        psf->lpVtbl->Release(psf);
    }

    if (idm_g == IDM_SENDTOFIRST) {
        AppendMenu(hmenu, MF_GRAYED | MF_DISABLED | MF_STRING, idm_g, TEXT("Send what sent to me to my sendto ^_^"));
    }
}

void SendTo_OnInitMenuPopup(HWND hwnd, HMENU hmenu, UINT item, BOOL fSystemMenu)
{
    if (GetMenuItemCount(hmenu) > 0) { return; }
    //
    if (hmenu == g_hmenuSendTo) { /* :p only top level */
        FolderToMenu(hwnd, hmenu, FOLDER_SENDTO);
    }
    else {
        MENUINFO mi;
        mi.cbSize = sizeof(mi);
        mi.fMask = MIM_HELPID;
        if (GetMenuInfo(hmenu, &mi)) {
            FolderToMenu(hwnd, hmenu, PSENDTO[mi.dwContextHelpID]);
        }
    }
}

void SendTo_SendToItem(HWND hwnd, int idm)
{
    HRESULT hres;

    FORKING = 1;
    //
    if (__argc == 1) {
        ShellExecute(NULL, NULL, PSENDTO[idm], NULL, NULL, SW_SHOWDEFAULT);
    }
    else {
        LPDATAOBJECT pdto;
        LPDROPTARGET pdt;
        hres = GetUIObjectOfPaths(hwnd, &PSENDTO[idm], 1, &IID_IDropTarget, (LPVOID*)&pdt);
        if (SUCCEEDED(hres)) {
            /* First convert all filenames to a data object. */
            hres = GetUIObjectOfPaths(hwnd, __targv   1, __argc - 1, &IID_IDataObject, (LPVOID*)&pdto);
            if (SUCCEEDED(hres)) {
                /* Now drop the file on the drop target. */
                DoDrop(pdto, pdt);
                pdt->lpVtbl->Release(pdt);
            }
        }
        pdto->lpVtbl->Release(pdto);
    }
    // Exit as done!
    FORKING = 0;
    PostQuitMessage(0);
}

void SendTo_OnCommand(HWND hwnd, int id, HWND hwndCtl, UINT codeNotify)
{
    SendTo_SendToItem(hwnd, id);
}

BOOL SendTo_OnCreate(HWND hwnd, LPCREATESTRUCT lpCreateStruct)
{
    g_hmenuSendTo = CreatePopupMenu();
    return TRUE;
}

/* UAC focus changes!!! */
void SendTo_OnKillFocus(HWND hwnd, HWND hwndOldFocus)
{
    if (FORKING == 0) PostQuitMessage(0);
}

LRESULT CALLBACK SendTo_WndProc(HWND hwnd, UINT uiMsg, WPARAM wParam, LPARAM lParam)
{
    switch (uiMsg) {

        HANDLE_MSG(hwnd, WM_CREATE, SendTo_OnCreate);

        HANDLE_MSG(hwnd, WM_INITMENUPOPUP, SendTo_OnInitMenuPopup);

        HANDLE_MSG(hwnd, WM_COMMAND, SendTo_OnCommand);

        HANDLE_MSG(hwnd, WM_KILLFOCUS, SendTo_OnKillFocus);

    }

    return DefWindowProc(hwnd, uiMsg, wParam, lParam);
}

BOOL InitApp(void)
{
    WNDCLASS wc;
    HRESULT hr;

    wc.style = 0;
    wc.lpfnWndProc = SendTo_WndProc;
    wc.cbClsExtra = 0;
    wc.cbWndExtra = 0;
    wc.hInstance = g_hinst;
    wc.hIcon = NULL;
    wc.hCursor = LoadCursor(NULL, IDC_ARROW);
    wc.hbrBackground = (HBRUSH)(COLOR_WINDOW   1);
    wc.lpszMenuName = NULL;
    wc.lpszClassName = TEXT("SendTo ");

    RegisterClass(&wc);

    hr = SHGetDesktopFolder(&g_psfDesktop);
    if (FAILED(hr)) {
        return FALSE;
    }

    FOLDER_SENDTO = calloc(T_MAX_PATH   1, sizeof(TCHAR));
    if (FOLDER_SENDTO == NULL) { return FALSE; }

    return TRUE;
}

void TermApp(void)
{
    int i, n;
    //
    if (g_psfDesktop) {
        g_psfDesktop->lpVtbl->Release(g_psfDesktop);
        g_psfDesktop = NULL;
    }
    n = idm_g - IDM_SENDTOFIRST;
    for (i = 0; i < n; i  ) {
        free(PSENDTO[i]);
        DeleteObject(&hBmpImageA[i]);
    }
    free(PSENDTO);
    //
    free(FOLDER_SENDTO);
    //
    free((void**)hBmpImageA);
}

int WINAPI _tWinMain(HINSTANCE hinst, HINSTANCE hinstPrev, LPTSTR lpCmdLine, int nCmdShow)
{
    MSG msg;
    HWND hwnd;
    HRESULT hrInit;
    POINT pt = { 0, 0 };
    //
    ULONG_PTR           gdiplusToken;
    GdiplusStartupInput gdiplusStartupInput = { 1, NULL, FALSE, TRUE }; //MUST!

    g_hinst = hinst;

    if (!InitApp()) return 1;

    if (GetFullPathName(TEXT("sendto"), T_MAX_PATH, FOLDER_SENDTO, NULL) == 0) { return 2; }
    //
    GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
    //
    hrInit = CoInitialize(NULL);

    hwnd = CreateWindow(
        TEXT("SendTo "),                /* Class Name */
        TEXT("lifenjoiner"),            /* Title */
        WS_POPUP,                       /* Style */
        CW_USEDEFAULT, CW_USEDEFAULT,   /* Position */
        0, 0,                           /* Size */
        NULL,                           /* Parent */
        NULL,                           /* No menu */
        hinst,                          /* Instance */
        0);                             /* No special parameters */

    SetWindowLong(hwnd, GWL_EXSTYLE, WS_EX_TOOLWINDOW);
    ShowWindow(hwnd, nCmdShow);

    // run once!
    GetCursorPos(&pt);
    TrackPopupMenu(g_hmenuSendTo, TPM_LEFTALIGN, pt.x, pt.y, 0, hwnd, NULL);
    //
    while (GetMessage(&msg, NULL, 0, 0)) {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }

    TermApp();
    //
    GdiplusShutdown(gdiplusToken);

    if (SUCCEEDED(hrInit)) {
        CoUninitialize();
    }

    return 0;
}

I can compile it successfully in VS Terminal Prompt with cl.exe /MD /Os /DUNICODE /D_UNICODE /Femain_x64.exe main.c Ole32.lib shell32.lib user32.lib Comdlg32.lib Shlwapi.lib gdi32.lib gdiplus.lib bufferoverflowU.lib. However, when I create a Visual Studio empty C project and add my main.c to it, it gives me this erro when trying to compile. enter image description here

enter image description here

Why these errors doesn't happen when using cl.exe? Is this a Visual Studio configuration issue?

CodePudding user response:

Visual Studio works on the project file, which contains a whole bunch of cl and link options, whereas when you run your cl command manually you run it with different arguments. It's normal to get different results.

Also note that the error you see from your project is correct, if NumOfpidls is 0 then your program will dereference a null variable. Edit: actually you don't even initialize it, so you'll dereference garbage. That truly is terrible code.

  • Related