Can I Write Version Information API For Both CHAR And WCHAR? - winapi

I'm a little bit short of reaching my goal.
GetFileVersionInfoSize() is working fine along with other two functions GetFileVersionInfo() and VerQueryValue(). I would like to just add more features to it to make it complete.
I've coded it to run on WCHAR and would like to know making it run for CHAR would make sense?
Is there a way around it so that I code it once and it would work for both?
Also, is there a way I could enumerate the contents of \\StringFileInfo\\lang-codepage\\* ?
DWORD GetFileVersionInfo3(const TCHAR *pszFilePath, std::vector<std::pair<std::wstring, std::wstring>> *lplist)
{
DWORD dwSize = 0;
BYTE *pbVersionInfo = NULL;
VS_FIXEDFILEINFO *pFileInfo = NULL;
UINT puLenFileInfo = 0;
dwSize = GetFileVersionInfoSize(pszFilePath, NULL);
if (dwSize == 0)
{
printf("\nError in GetFileVersionInfoSize: %d\n", GetLastError());
return 1;
}
pbVersionInfo = new BYTE[dwSize];
memset(pbVersionInfo, '\0', dwSize);
if (!GetFileVersionInfo(pszFilePath, 0, dwSize, pbVersionInfo))
{
printf("\nError in GetFileVersionInfo: %d\n", GetLastError());
delete[] pbVersionInfo;
return 1;
}
if (!VerQueryValue(pbVersionInfo, TEXT("\\"), (LPVOID*)&pFileInfo, &puLenFileInfo))
{
printf("\nError in VerQueryValue: %d\n", GetLastError());
delete[] pbVersionInfo;
return 1;
}
if (!VerQueryValue(pbVersionInfo, TEXT("\\VarFileInfo\\Translation"), (LPVOID*)&lpTranslate, &puLenFileInfo))
{
printf("\nError in VerQueryValue: %d\n", GetLastError());
return 1;
}
std::vector<std::wstring>::iterator itr;
std::vector<std::wstring> wlist;
wlist.clear();
wlist.push_back(L"FileDescription");
wlist.push_back(L"InternalName");
wlist.push_back(L"OriginalFilename");
wlist.push_back(L"CompanyName");
wlist.push_back(L"FileVersion");
wlist.push_back(L"ProductName");
wlist.push_back(L"ProductVersion");
wlist.push_back(L"LegalCopyright");
char fileEntry[1024];
for (int i = 0; i < (puLenFileInfo / sizeof(struct LANGANDCODEPAGE)); i++)
{
sprintf_s(fileEntry, 1024, "\\StringFileInfo\\%04x%04x\\",
lpTranslate[i].wLanguage,
lpTranslate[i].wCodePage);
lplist->push_back(std::pair<std::wstring, std::wstring>(L"File: ", pszFilePath));
std::string s1(fileEntry);
for (itr = wlist.begin(); itr != wlist.end(); itr++)
{
std::wstring item = *itr;
std::wstring wstr;
wstr.append(s1.begin(), s1.end());
wstr.append(item);
LPVOID lpBuffer = NULL;
UINT dwBytes = 0;
bool bRes = VerQueryValue(pbVersionInfo, wstr.c_str(), (LPVOID*)&lpBuffer, &dwBytes);
if (!bRes)
{
continue;
}
LPTSTR wsResult;
wsResult = (LPTSTR)lpBuffer;
lplist->push_back(std::pair<std::wstring, std::wstring>(item, wsResult));
}
}
return 0;
}

Since you are using TCHAR, use std:::basic_string<TCHAR> instead of std::wstring to match. Otherwise, drop TCHAR and use WCHAR for everything.

Related

I want to break this into multiple functions what data type can i use?

There's more code than this, but I'm retrieving data from multiple edit controls and an external file to count currency. I want to break this down into multiple smaller functions, but I don't know what data type it would use to run successfully.
HANDLE hBuck = CreateFile(FileName, GENERIC_ALL, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
DWORD bytes_read;
DWORD leni = GetFileSize(hBuck, NULL);
LPSTR buffer = (LPSTR)GlobalAlloc(GPTR, leni +1);
ReadFile(hBuck, buffer, leni, &bytes_read, NULL);
double xt = atof(buffer);
CloseHandle(hBuck);
DWORD len = GetWindowTextLength(hPen) +1;
buffer = (LPSTR)GlobalAlloc(GPTR, len +1);
GetWindowText(hPen, buffer, len);
double num1 = atof(buffer);
len = GetWindowTextLength(hNick) +1;
buffer = (LPSTR)GlobalAlloc(GPTR, len +1);
GetWindowText(hNick, buffer, len);
double num2 = atof(buffer);
len = GetWindowTextLength(hDime) +1;
buffer = (LPSTR)GlobalAlloc(GPTR, len +1);
GetWindowText(hDime, buffer, len);
double num3 = atof(buffer);
len = GetWindowTextLength(hQuart) +1;
buffer = (LPSTR)GlobalAlloc(GPTR, len +1);
GetWindowText(hQuart, buffer, len);
double num4 = atof(buffer);
Try something like this:
bool ReadDoubleFromFile(LPCSTR FileName, double *value)
{
if (!value) return false;
*value = 0.0;
HANDLE hBuck = CreateFile(FileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (hBuck == INVALID_HANDLE_VALUE) return false;
DWORD len = GetFileSize(hBuck, NULL);
if (len == INVALID_FILE_SIZE) {
CloseHandle(hBuck);
return false;
}
LPSTR buffer = (LPSTR) LocalAlloc(LPTR, len + 1);
if (!buffer) {
CloseHandle(hBuck);
return false;
}
DWORD bytes_read;
if (!ReadFile(hBuck, buffer, len, &bytes_read, NULL)) {
LocalFree((HLOCAL)buffer);
CloseHandle(hBuck);
return false;
}
CloseHandle(hBuck);
*value = atof(buffer);
LocalFree((HLOCAL)buffer);
return true;
}
bool ReadDoubleFromEdit(HWND hEdit, double *value)
{
if (!value) return false;
*value = 0.0;
DWORD len = GetWindowTextLengthA(hEdit);
if (len > 0) {
++len;
LPSTR buffer = (LPSTR) LocalAlloc(LPTR, len);
if (!buffer) return false;
if (!GetWindowTextA(hEdit, buffer, len)) {
LocalFree((HLOCAL)buffer);
return false;
}
*value = atof(buffer);
LocalFree((HLOCAL)buffer);
}
return true;
}
...
double xt, num1, num2, num3, num4;
if (ReadDoubleFromFile(FileName, &xt) &&
ReadDoubleFromEdit(hPen, &num1) &&
ReadDoubleFromEdit(hNick, &num2) &&
ReadDoubleFromEdit(hDime, &num3) &&
ReadDoubleFromEdit(hQuart, &num4))
{
// use values as needed...
}
else
{
// error
}
On the other hand, if you are using C++ instead of C (you did not say which language you are using), this becomes a bit simpler:
double ReadDoubleFromFile(const std::string &FileName)
{
std::ifstream inFile;
inFile.exceptions(std::ifstream::failbit);
inFile.open(FileName.c_str());
double value;
inFile >> value;
return value;
}
double ReadDoubleFromEdit(HWND hEdit)
{
double value = 0.0;
DWORD len = GetWindowTextLength(hEdit);
if (len > 0) {
std::basic_string<TCHAR> buffer(len, TEXT('\0'));
if (!GetWindowText(hEdit, buffer.data(), len + 1))
throw std::runtime_error("GetWindowText failed");
value = std::stod(buffer);
}
return value;
}
...
try
{
double xt = ReadDoubleFromFile(FileName);
double num1 = ReadDoubleFromEdit(hPen);
double num2 = ReadDoubleFromEdit(hNick);
double num3 = ReadDoubleFromEdit(hDime);
double num4 = ReadDoubleFromEdit(hQuart);
// use values as needed...
}
catch (const std::exception &ex)
{
// handle error as needed...
}

winsock time loop send message does not work

Using winsock, I got a client and a server, when connect is done and i send a message the first time i can recv it in the server but after that when I do a time loop i can not show them on the screen. the send message inside the time loop does not return an error. I know this is a weird problem but if you take a look at timerCb that's where the send function is, it does not return an error but in my server i cannot print it. I have also tried making a new while loop with a parameter of recv it still did not work.
This is my client,
char receivingMessage[1000];
char messageInitiation[90] = "Hello YUMATKARA, conn pls bro hhhasf7sasflljh89";
VOID CALLBACK timerCb(HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime);
//main
SetTimer(NULL, 0, 3600, timerCb);
if(WSAStartup(MAKEWORD(2, 2), &ws) != 0){
printf("WSA err %d \n", GetLastError());
}else{
}
if((s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET){
printf("Invalid Socket \n");
}else{
printf("socket binded \n");
}
rmtServer.sin_addr.s_addr = inet_addr("127.0.0.1");
rmtServer.sin_port = htons(4743);
rmtServer.sin_family = AF_INET;
if((connect(s, (struct sockaddr*)&rmtServer, sizeof(struct sockaddr_in))) != 0){
printf("\n err %d", GetLastError());
}else{
printf("\n connected");
send(s, messageInitiation, strlen(messageInitiation), 0);
recv(s, receivingMessage, 1000, 0);
printf("\n %s", receivingMessage);
int liop;
liop = strcmp(receivingMessage, "I got you!!");
if(liop == 0){
connectedYet = TRUE;
}
printf("\n is it true: ? %d\n", connectedYet);
}
while(GetMessage(&message, NULL, 0, 0) > 0){
TranslateMessage(&message);
DispatchMessage(&message);
}
//outside main
VOID CALLBACK timerCb(HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime){
char *msgg = "Hello YUMATKARA, conn pls bro hhhasf7sasflljh89";
printf("\n%s\n", "timing");
if(send(s, msgg, strlen(msgg), 0) == SOCKET_ERROR){
printf("err :%d\n", GetLastError());
}
}
And this is my server
#include <windows.h>
#include <winsock2.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdParam, int iCmdShow) {
MSG message;
WSADATA ws;
SOCKET s, incomingSocket;
struct sockaddr_in server, client;
char incomingMessage[1800];
int recvState;
WSAStartup(MAKEWORD(2, 2), &ws);
s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
server.sin_port = htons(4743);
server.sin_addr.s_addr = inet_addr("127.0.0.1");
server.sin_family = AF_INET;
bind(s, (struct sockaddr *)&server, sizeof(server));
listen(s, 1300);
int g = sizeof(struct sockaddr_in);
while((incomingSocket = accept(s, (struct sockaddr *)&client, &g)) != INVALID_SOCKET){
printf("%s\n", inet_ntoa(client.sin_addr));
printf("conn\n");
if((recvState = recv(incomingSocket, incomingMessage, 2500, 0)) == SOCKET_ERROR){
}else{
int as;
if((as = strcmp(incomingMessage, "Hello YUMATKARA, conn pls bro hhhasf7sasflljh89")) == 0){
printf("\n identical");
send(incomingSocket, "I got you!!", 11, 0);
}
printf("\n :%s\n", incomingMessage);
}
}
if(incomingSocket == INVALID_SOCKET){
printf("invalid socket");
}
return 0;
}
UPDATE
I have added this in my server code, before return 0 it does not display anything at all.
while((recvState = recv(incomingSocket, incomingMessage, 50, 0)) > 0) {
printf("\n new msg %s\n", incomingMessage);
}
TCP is a byte stream, not message-oriented like you are expecting.
recv() is not guaranteed to return complete messages. It could return as little as 1 byte, or it could return partial bytes from a message, or even bytes from multiple messages. You have to handle buffering and message framing in your code logic. And pay attention to its return value so you know how much it actually read. If you are expecting more data than is read, you have to call recv() again to read the rest, potentially many times. So use a loop.
So, either:
Have the sender send a string's length as a fixed-length value before then sending the actual characters. Then have the receiver read the length to know how many characters to read.
Have the sender send a unique terminator after each string, like a nul character or even a CRLF, then the receiver can keep reading until it encounters the terminator.
As for send(), it is not guaranteed to send complete data, either. It could send as few as 1 byte, or at least less than what you requested. So you have to pay attention to its return value, too, to know how much it actually sent. If it doesn't send everything in one go, you have to call it again to send any remaining data, potentially many times. So use a loop.
For example, try something more like this:
Client:
const char messageInitiation* = "Hello YUMATKARA, conn pls bro hhhasf7sasflljh89";
char* readStr(SOCKET s)
{
char *str = NULL;
char buffer[100], ch;
int buf_len = 0, str_len = 0, ret;
do
{
ret = recv(s, &ch, 1, 0);
if (ret == SOCKET_ERROR)
{
printf("recv err %d\n", WSAGetLastError());
return SOCKET_ERROR;
}
if (ch == '\0')
break;
if (buf_len == sizeof(buffer))
{
char *newstr = (char*) realloc(str, str_len + buf_len + 1);
if (!newstr)
{
printf("memory err\n");
free(str);
return NULL;
}
str = newstr;
memcpy(str + str_len, buffer, buf_len);
str_len += buf_len;
buf_len = 0;
}
buffer[buf_len++] = ch;
}
while (true);
if (buf_len > 0)
{
char *newstr = (char*) realloc(str, str_len + buf_len + 1);
if (!newstr)
{
printf("memory err\n");
free(str);
return NULL;
}
str = newstr;
memcpy(str, buffer, buf_len);
str_len += buf_len;
}
str[str_len] = '\0';
return str;
}
int sendStr(SOCKET s, const char *str)
{
const unsigned char *pstr = (const unsigned char*) str;
int len = strlen(str) + 1, ret;
do
{
ret = send(s, pstr, len, 0);
if (ret == SOCKET_ERROR)
{
printf("send err %d\n", WSAGetLastError());
return SOCKET_ERROR;
}
pstr += ret;
len -= ret;
}
while (len > 0);
return 0;
}
/* alternatively:
int readAll(SOCKET s, void *data, int len)
{
unsigned char *pdata = (unsigned char *) data;
int ret;
while (len > 0)
{
ret = recv(s, pdata, len, 0);
if (ret == SOCKET_ERROR)
{
printf("recv err %d\n", WSAGetLastError());
return SOCKET_ERROR;
}
pdata += ret;
len -= ret;
}
return 0;
}
int readStr(SOCKET s)
{
int32_t len = 0;
if (readAll(s, &len, sizeof(len)) == SOCKET_ERROR)
return NULL;
char *str = (char*) malloc(len + 1);
if (!str)
{
printf("memory err\n");
return NULL;
}
if (readAll(s, str, len) == SOCKET_ERROR)
{
free(str);
return NULL;
}
str[len] = '\0';
return str;
}
int sendAll(SOCKET s, const void *data, int len)
{
const unsigned char *pdata = (const unsigned char*) data;
int ret;
while (len > 0)
{
ret = send(s, pdata, len, 0);
if (ret == SOCKET_ERROR)
{
printf("send err %d\n", WSAGetLastError());
return SOCKET_ERROR;
}
pdata += ret;
len -= ret;
}
return 0;
}
int sendStr(SOCKET s, const char *str)
{
int32_t len = strlen(str) + 1;
int ret = sendAll(s, &len, sizeof(len));
if (ret == 0)
ret = sendAll(s, str, len);
return ret;
}
*/
VOID CALLBACK timerCb(HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime)
{
printf("\n%s\n", "timing");
if (!sendStr(s, messageInitiation))
PostQuitMessage(0);
}
int main()
{
WSADATA ws;
int ret = WSAStartup(MAKEWORD(2, 2), &ws);
if (ret != 0)
{
printf("WSA err %d\n", ret);
return -1;
}
SOCKET s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (s == INVALID_SOCKET)
{
printf("socket err %d\n", WSAGetLastError());
WSACleanup();
return -1;
}
printf("socket created\n");
struct sockaddr_in rmtServer = {};
rmtServer.sin_family = AF_INET;
rmtServer.sin_addr.s_addr = inet_addr("127.0.0.1");
rmtServer.sin_port = htons(4743);
if (connect(s, (struct sockaddr*)&rmtServer, sizeof(struct sockaddr_in)) == SOCKET_ERROR)
{
printf("connect err %d\n", WSAGetLastError());
closesocket(s);
WSACleanup();
return -1;
}
printf("connected\n");
if (sendStr(s, messageInitiation) != 0)
{
closesocket(s);
WSACleanup();
return -1;
}
char *receivingMessage = recvStr(s);
if (!receivingMessage)
{
closesocket(s);
WSACleanup();
return -1;
}
printf("%s\n", receivingMessage);
BOOL connectedYet = (strcmp(receivingMessage, "I got you!!") == 0);
printf("is it true: ? %d\n", connectedYet);
free(receivingMessage);
SetTimer(NULL, 0, 3600, timerCb);
MSG message;
while (GetMessage(&message, NULL, 0, 0) > 0)
{
TranslateMessage(&message);
DispatchMessage(&message);
}
closesocket(s);
WSACleanup();
return 0;
}
Server:
#include <windows.h>
#include <winsock2.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// see client code above
char* readStr(SOCKET s);
int sendStr(SOCKET s, const char *str);
int main()
{
struct sockaddr_in server = {0}, client;
WSADATA ws;
int ret = WSAStartup(MAKEWORD(2, 2), &ws);
if (ret != 0)
{
printf("WSA err %d\n", ret);
return -1;
}
SOCKET s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (s == INVALID_SOCKET)
{
printf("socket err %d\n", WSAGetLasatError());
WSACleanup();
return -1;
}
struct sockaddr_in server = {};
server.sin_family = AF_INET;
server.sin_addr.s_addr = inet_addr("127.0.0.1");
server.sin_port = htons(4743);
ret = bind(s, (struct sockaddr *)&server, sizeof(server));
if (ret == SOCKET_ERROR)
{
printf("bind err %d\n", WSAGetLastError());
closesocket(s);
WSACleanup();
return -1;
}
if (listen(s, 10) == SOCKET_ERROR)
{
printf("listen err %d\n", WSAGetLastError());
closesocket(s);
WSACleanup();
return -1;
}
int g, iResult;
struct sockaddr_in client;
do
{
g = sizeof(client);
SOCKET incomingSocket = accept(s, (struct sockaddr *)&client, &g);
if (incomingSocket == INVALID_SOCKET)
{
printf("accept err %d\n", WSAGetLastError());
closesocket(s);
WSACleanup();
return -1;
}
printf("%s conn\n", inet_ntoa(client.sin_addr));
char *incomingMessage = recvStr(incomingSocket);
if (incomingMessage)
{
printf("%s\n", incomingMessage);
if (incomingMessage, "Hello YUMATKARA, conn pls bro hhhasf7sasflljh89") == 0)
{
printf("identical\n");
sendStr(incomingSocket, "I got you!!");
}
}
closesocket(incomingSocket);
}
while (true);
return 0;
}

computing hashValue of a file

Small piece of code I wrote to list files in a dummy directory and then calculate the hash values.
But when I pass the filename to the calc_hash function , program terminates after computing the hash of two files... with error Unhandled exception at 0x77406850 in hashtest3-cpp.exe: 0xC0000005: Access violation writing location 0x64333782.
Can someone please point out the error ....
code snippet::
#include <stdio.h>
#include <windows.h>
#include <Wincrypt.h>
#include <strsafe.h>
#include <string.h>
#include <tchar.h>
#include <iostream>
using namespace std;
#define BUFSIZE 1024
#define MD5LEN 16
//======================================================VARIABLE INITIALIZATION
DWORD Status = 0;
BOOL bResult = FALSE;
ULONG_PTR hProv = 0;
ULONG_PTR hHash = 0;
HANDLE hFile = NULL;
DWORD i;
DWORD j=0;
BYTE rgbFile[BUFSIZE];
DWORD cbRead = 0;
BYTE rgbHash[MD5LEN];
DWORD cbHash = 0;
LPTSTR filename;
CHAR resultstream[33];
HANDLE hFind;
WIN32_FIND_DATA data;
TCHAR filepath[260] = _T("");
LPWSTR FNAME;
LPWSTR FULLPATH = L"c:\\test\\";
LPWSTR dir = L"c:\\test\\*.*";
LPWSTR DEFAULt = L"";
CHAR rgbDigits[] = "0123456789abcdef";
//=====================================================FUNCTION DECLARATION
void list_files(void);
void calc_hash(void);
//======================================================MAIN START
int main()
{
list_files();
//calc_hash();
getchar();
return 0;
}
//======================================================LISTING FILES IN A DIRECTORY
void list_files()
{
hFind = FindFirstFile(dir, &data);
if (hFind != INVALID_HANDLE_VALUE)
{
do
{
StringCchCopy(filepath, 260, DEFAULt);
resultstream[33] = '\0';
DWORD j=0;
FNAME = data.cFileName;
StringCchCat(filepath, 260, FULLPATH);
StringCchCat(filepath, 260, FNAME);
filename = (LPTSTR)filepath;
printf("\n%ws", filename);
/*calc_hash();
getchar();*/
continue;
}while (FindNextFile(hFind, &data));
}
getchar();
}
//======================================================HASH OF A FILE
void calc_hash()
{
hFile = CreateFile(
filename,
GENERIC_READ,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
FILE_FLAG_SEQUENTIAL_SCAN,
NULL
);
if (INVALID_HANDLE_VALUE == hFile)
{
Status = GetLastError();
//printf("\nerror opening file::%d", Status);
goto end;
}
// Get handle to the crypto provider
if (!CryptAcquireContext(
&hProv,
NULL,
NULL,
PROV_RSA_FULL,
CRYPT_VERIFYCONTEXT))
{
Status = GetLastError();
printf("CryptAcquireContext error:: %d\n", Status);
CloseHandle(hFile);
getchar();
goto end;
}
if (!CryptCreateHash(hProv, CALG_MD5, 0, 0, &hHash))
{
Status = GetLastError();
printf("CryptAcquireContext error:: %d\n", Status);
CloseHandle(hFile);
CryptReleaseContext(hProv, 0);
getchar();
goto end;
}
while (bResult = ReadFile(hFile, rgbFile, BUFSIZE, &cbRead, NULL))
{
if (0 == cbRead)
{
break;
}
if (!CryptHashData(hHash, rgbFile, cbRead, 0))
{
Status = GetLastError();
printf("CryptHashData error:: %d\n", Status);
CryptReleaseContext(hProv, 0);
CryptDestroyHash(hHash);
CloseHandle(hFile);
getchar();
goto end;
}
}
//================================GENERATING RESULT=============================
if (!bResult)
{
Status = GetLastError();
printf("ReadFile error:%S:: %d\n",filename, Status);
CryptReleaseContext(hProv, 0);
CryptDestroyHash(hHash);
CloseHandle(hFile);
getchar();
goto end;
}
cbHash = MD5LEN;
if (CryptGetHashParam(hHash, HP_HASHVAL, rgbHash, &cbHash, 0))
{
printf("MD5 hash of file %ws is:- ", filename);
for (i = 0; i < cbHash; i++)
{
resultstream[j]=rgbDigits[rgbHash[i] >> 4];
j++;
resultstream[j]=rgbDigits[rgbHash[i] & 0xf];
j++;
}
resultstream[j] = '\0';
printf("\n%s", resultstream );
printf("\n");
}
else
{
Status = GetLastError();
printf("CryptGetHashParam error:: %d\n", Status);
}
CryptDestroyHash(hHash);
CryptReleaseContext(hProv, 0);
CloseHandle(hFile);
end:;
//getchar();
}
The problem is you declare resultstream as
CHAR resultstream[33];
but then you use in your code
resultstream[33] = '\0';
The resultstream array is 0 indexed so valid values are 0-32, you are accessing memory not allocated for that array (hence the "Access violation")

How can I get the Primary access token in windows 8?

I want to get the primary token so that I can get the access of OpenInputDesktop() and do my necessary things.
I browsed all over the sites for help and found the conclusive code as below but I got an error on calling DuplicateTokenEx() is 998 which means invalid access to memory location.
HANDLE GetCurrentUserToken()
{
HANDLE currentToken = 0;
PHANDLE primaryToken = 0;
unsigned int winlogonPid = 0;
int dwSessionId = 0;
PHANDLE hUserToken = 0;
PHANDLE hTokenDup = 0;
PWTS_SESSION_INFO pSessionInfo = 0;
DWORD dwCount = 0;
WTSEnumerateSessions(WTS_CURRENT_SERVER_HANDLE, 0, 1,
&pSessionInfo, &dwCount);
//TestLog("Error on WTSEnumerateSessions(): %d",GetLastError());
int dataSize = sizeof(WTS_SESSION_INFO);
for (DWORD i = 0; i < dwCount; ++i)
{
WTS_SESSION_INFO si = pSessionInfo[i];
if (WTSActive == si.State)
{
dwSessionId = si.SessionId;
break;
}
}
WTSFreeMemory(pSessionInfo);
array<Process^>^localByName = Process::GetProcessesByName( "winlogon" );
for (int i=0;i<localByName->Length;i++)
{
Process ^ p1 = (Process^)(localByName->GetValue(i));
if ((unsigned int)p1->SessionId == dwSessionId)
{
winlogonPid = (unsigned int)p1->Id;
}
}
// obtain a handle to the winlogon process
HANDLE hProcess = OpenProcess(MAXIMUM_ALLOWED, false, winlogonPid);
TestLog("Error on OpenProcess():",GetLastError());
// obtain a handle to the access token of the winlogon process
if (!OpenProcessToken(hProcess, TOKEN_DUPLICATE, &currentToken))
{
TestLog("Error on OpenProcessToken():",GetLastError());
CloseHandle(hProcess);
return false;
}
BOOL bRet ;
// bRet = DuplicateTokenEx(currentToken,
// MAXIMUM_ALLOWED /*TOKEN_ASSIGN_PRIMARY | TOKEN_ALL_ACCESS*/,
// NULL/*0*/,
// SecurityImpersonation, TokenImpersonation, primaryToken);
bRet = DuplicateTokenEx(currentToken,
TOKEN_ASSIGN_PRIMARY | TOKEN_ALL_ACCESS,
NULL, SecurityImpersonation,
TokenPrimary, primaryToken);
TestLog("Error on DuplicateTokenEx():",GetLastError());
TestLog("return value of DuplicateTokenEx()",bRet);
int errorcode = GetLastError();
if (bRet == false)
{
return 0;
}
return primaryToken;
}
int main(array<System::String ^> ^args)
{
Console::WriteLine(L"Hello World");
TestLog("**Start TestLaunchExeOneTime**",0);
HANDLE hTokenNew = NULL, hTokenDup = NULL;
HMODULE hmod = LoadLibrary(L"kernel32.dll");
hTokenDup = GetCurrentUserToken();
STARTUPINFO si;
PROCESS_INFORMATION pi;
memset(&si,0,sizeof(STARTUPINFO));
si.cb = sizeof( STARTUPINFO );
si.lpDesktop = L"winsta0\\default";
LPVOID pEnv = NULL;
DWORD dwCreationFlag = NORMAL_PRIORITY_CLASS | CREATE_NEW_CONSOLE;
HMODULE hModule = LoadLibrary(L"Userenv.dll");
if(hModule )
{
if(CreateEnvironmentBlock(&pEnv,hTokenDup,FALSE))
{
//WriteToLog("CreateEnvironmentBlock Ok");
dwCreationFlag |= CREATE_UNICODE_ENVIRONMENT;
}
else
{
TestLog("Error on CreateEnvironmentBlock():",GetLastError());
pEnv = NULL;
}
}
//
if ( !CreateProcessAsUser( hTokenDup,
NULL,
L"C:\\temp\\DesktopDuplicationmilliseconds.exe",
NULL,
NULL,
FALSE,
dwCreationFlag,
pEnv,
NULL,
&si,
&pi
))
{
}
else
{
TestLog("Error on CreateProcessAsUser():",GetLastError());
// printf("error : %d",GetLastError());
}
return 0;
}
You haven't allocated any memory for the primary token. The primaryToken variable is a pointer to a handle, but you haven't actually pointed it to anything. (You've also declared GetCurrentUserToken as a function that returns a handle, but are actually returning a pointer to a handle.)
You need to either explicitly allocate the memory for the handle:
primaryToken = malloc(sizeof(HANDLE));
[...]
return *primaryToken;
or, more sensibly, define primaryToken as a HANDLE rather than a pointer and pass a reference to it in the appropriate place:
HANDLE primaryToken;
[...]
bRet = DuplicateTokenEx(currentToken,
TOKEN_ASSIGN_PRIMARY | TOKEN_ALL_ACCESS,
NULL, SecurityImpersonation,
TokenPrimary, &primaryToken);

GdipCreateBitmapFromStream change of contract on Windows 7?

We have a perfectly functional app that just broke on Windows 7 because (the GDI+ primitive) GdipCreateBitmapFromStream refuses JPEG images presented to it (without problem on XP and even Vista).
We don't directly call GDI+, we call the documented ATL CImage class, and it calls that, and gets the error.
It's our own OLE stream implementation.
Has anyone seen a way around this?
Here is a complete test case:
#include <atlbase.h>
#include <atlimage.h>
#include <gdiplus.h>
#include <time.h>
#include <sys/stat.h>
// GSMemoryStream.h : Declaration of the GSMemoryStream
/* No ATL or class factory support is needed here. You get one of these via "new", with zero reference count...
Image.Load(IStreamPtr(new GSMemoryStream(ptr, len));
and the smart pointer will provoke its deletion at the right time....
*/
// GSMemoryStream
class GSMemoryStream :
public IStream
{
private:
ULONG m_Length;
ULONG m_CurPtr;
PBYTE m_Base;
int m_rc;
public:
GSMemoryStream(PBYTE _p, DWORD _len) {
m_Length = _len;
m_CurPtr = 0;
m_Base = _p;
m_rc = 0;
}
GSMemoryStream () {
m_Length = 0;
m_CurPtr = 0;
m_Base = NULL;
m_rc = 0;
}
STDMETHODIMP Read(void *,ULONG,ULONG *);
STDMETHODIMP Write(const void *,ULONG,ULONG *) {return E_FAIL;}
STDMETHODIMP Seek(LARGE_INTEGER,DWORD,ULARGE_INTEGER *);
STDMETHODIMP SetSize(ULARGE_INTEGER) {return E_FAIL;}
STDMETHODIMP CopyTo(IStream *,ULARGE_INTEGER,ULARGE_INTEGER *,ULARGE_INTEGER *);
STDMETHODIMP Commit(DWORD) {return S_OK;}
STDMETHODIMP Revert(void) {return S_OK;}
STDMETHODIMP LockRegion(ULARGE_INTEGER,ULARGE_INTEGER,DWORD) {return S_OK;}
STDMETHODIMP UnlockRegion(ULARGE_INTEGER,ULARGE_INTEGER,DWORD) {return S_OK;}
STDMETHODIMP Stat(STATSTG *,DWORD);
STDMETHODIMP Clone(IStream ** ) {return E_FAIL;}
STDMETHODIMP QueryInterface(const IID & iid,void ** d) throw() {
if (IsEqualGUID(iid, IID_IUnknown) || IsEqualGUID (iid, __uuidof(IStream))) {
*d = (PVOID)this;
AddRef();
return S_OK;
}
return E_FAIL;
}
ULONG STDMETHODCALLTYPE AddRef(void) throw() {
m_rc++;
return S_OK;
}
ULONG STDMETHODCALLTYPE Release(void) throw() {
if (--m_rc == 0)
delete this; // can never go negative, because the m_rc won't be around any more once it is 0.
// so it's not even meaningful to test for it and breakpoint or throw.
return S_OK;
}
};
// CGSMemoryStream
STDMETHODIMP GSMemoryStream::Read(void * p,ULONG n, ULONG * pNread) {
ATLTRACE(L"GSMS$Read p %p bufct %d m_curptr %d\r\n", p, n, m_CurPtr);
if ((n + m_CurPtr) > m_Length)
n = m_Length - m_CurPtr;
memcpy(p, m_Base + m_CurPtr, n);
if (pNread)
*pNread = n;
m_CurPtr += n;
ATLTRACE(L"GSMS$Read(final) n %d m_CurPtr %d\r\n", n, m_CurPtr);
return S_OK;
}
STDMETHODIMP GSMemoryStream::Seek(LARGE_INTEGER pos,DWORD type,ULARGE_INTEGER * newpos) {
LONG lpos = (LONG)pos.LowPart;
ATLTRACE(L"GSMS$Seek type %d lpos %d m_CurPtr %d\r\n", type, lpos, m_CurPtr);
switch (type) {
case STREAM_SEEK_SET:
if (lpos < 0 || lpos > (LONG) m_Length)
return E_POINTER;
m_CurPtr = (ULONG)lpos;
break;
case STREAM_SEEK_CUR:
if (lpos + m_CurPtr < 0 || lpos + m_CurPtr > m_Length)
return E_POINTER;
m_CurPtr += lpos;
break;
case STREAM_SEEK_END:
if (lpos > 0)
lpos = -lpos;
if (lpos + m_Length < 0)
return E_POINTER;
m_CurPtr = m_Length + lpos;
break;
default:
return E_FAIL;
}
ATLTRACE(L"GSMS$Seek end m_CurPtr %d\r\n", m_CurPtr);
if (newpos) {
newpos->HighPart = 0;
newpos->LowPart = m_CurPtr;
}
return S_OK;
}
STDMETHODIMP GSMemoryStream::CopyTo(IStream * pstm,ULARGE_INTEGER cb,ULARGE_INTEGER * pNread,ULARGE_INTEGER * pNwritten){
ATLTRACE("GSMS$CopyTo\r\n");
if (cb.HighPart)
return E_INVALIDARG;
ULONG n = cb.LowPart;
if ((n + m_CurPtr) > m_Length)
n = m_Length - m_CurPtr;
ULONG nwritten = 0;
HRESULT hr = pstm->Write(m_Base+m_CurPtr, n, &nwritten);
if (nwritten < n)
nwritten = n;
if (pNread) {
pNread->HighPart = 0;
pNread->LowPart = n;
}
if (pNwritten) {
pNwritten->HighPart = 0;
pNwritten->LowPart = nwritten;
}
m_CurPtr += n;
return hr;
}
STDMETHODIMP GSMemoryStream::Stat(STATSTG * ps,DWORD krazyflag) {
ATLTRACE(L"GSMS$Stat kf %d\r\n", krazyflag);
memset(ps, 0, sizeof(STATSTG));
ps->type = STGTY_STREAM;
ps->cbSize.LowPart = m_Length;
ps->cbSize.HighPart = 0;
#if 0
ps->mtime = (DWORD)time(NULL);
ps->ctime = (DWORD)time(NULL);
ps->atime = (DWORD)time(NULL);
#endif
return S_OK;
}
int main (int argc, char ** argv) {
if (argc < 2) {
fprintf(stderr, "Need image file pathname\n");
exit(2);
}
struct _stat SSTAT;
const char* fn = argv[1];
int failed = _stat(fn, &SSTAT);
if (failed) {
fprintf(stderr, "Can't open file: %s\n", fn);
exit(3);
}
size_t len = SSTAT.st_size;
printf ("Len = %d\n", len);
FILE* f = fopen(fn, "rb");
unsigned char * buf = new unsigned char [len];
size_t got = fread (buf, 1, len, f);
printf ("Got = %d\n", got);
fclose(f);
CoInitialize(NULL);
Gdiplus::GdiplusStartupInput gdiplusStartupInput;
ULONG_PTR gdiplusToken;
Gdiplus::GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
GSMemoryStream G(buf, len);
CImage cim;
HRESULT hr = cim.Load(&G);
printf("HRESULT = 0x%08X\n", hr);
delete [] buf;
CoUninitialize();
return 0;
}
Have you tried using the documented Bitmap object instead of using the undocumented GDI+ entrypoints?
Further research reveals that W7 queries an additional optional interface on the stream, and it's essential to return E_NOINTERFACE instead of E_NOTIMPL for it.

Resources