I'm writing the 32bit service app where I want to be able to launch Start menu items for the logged users. I did manage to accomplish this task by impersonating user and launching selected .lnk-file using CreateProcessAsUser with command-line: %windir%\system32\cmd /c " start /b /i "" "<path-to-lnk-file>" "
. And it works for almost every shortcut except bunch of the system shortcuts from Accessories folder (e.g. Sticky Notes.lnk, Snipping Tool.lnk). During the launch of the Snipping Tool I'm receiving the message box with this error from cmd:
Windows cannot find 'C:\ProgramData\Microsoft\Windows\Start Menu\Programs\Accessories\Snipping Tool.lnk'. Make sure you typed the name correctly, and then try again.
But the .lnk-file exists in this very directory!
Summary:
- service is 32 bit
- Windows 8 Pro x64
- launching shortcuts by user impersonation and CreateProcessAsUser with command-line
%windir%\system32\cmd /c " start /b /i "" "<path-to-lnk-file>" "
- approach works for almost every shortcut in Start menu except some in Start/Accessories folder (not all of them, e.g. Paint.lnk opens fine)
example code:
int launchAppForCurrentLoggedUser() { HANDLE userToken = WTSApiHelper::currentLoggedUserToken(); if (userToken == INVALID_HANDLE_VALUE) { return -1; } //Duplicating token with access TOKEN_DUPLICATE | TOKEN_ALL_ACCESS, //impersonation level SecurityImpersonation and token type TokenPrimary. //Also closing original userToken HANDLE dup = WTSApiHelper::duplicateToken(userToken); if (dup == INVALID_HANDLE_VALUE) { return -1; } int res = -1; uint8 *env = NULL; BOOL succeeded = CreateEnvironmentBlock((LPVOID *)&env, dup, FALSE); if (!succeeded) { Log("failed to get environment variables for user (error 0x%x).", GetLastError()); } PROCESS_INFORMATION pi; memset(&pi, 0, sizeof(PROCESS_INFORMATION)); STARTUPINFOW si; memset(&si, 0, sizeof(STARTUPINFOW)); si.cb = sizeof(STARTUPINFOW); si.lpDesktop = L"winsta0\\Default"; WCHAR params[] = L"/c \" start /b /i \"\" \"C:\\ProgramData\\Microsoft\\Windows\\Start Menu\\Programs\\Accessories\\Snipping Tool.lnk\" \" "; WCHAR cmd[] = L"C:\\Windows\\system32\\cmd.exe"; DWORD flags = env ? CREATE_UNICODE_ENVIRONMENT : 0; succeeded = CreateProcessAsUserW(dup, cmd, params, NULL, NULL, FALSE, flags | CREATE_NO_WINDOW, env, NULL, &si, &pi); if (!succeeded) { Log("cannot launch process for user with error 0x%x.", GetLastError()); } else { nres = 0; } DestroyEnvironmentBlock(env); CloseHandle(dup); return nres; }
What do I miss here?