diff --git a/meshconsole/main.c b/meshconsole/main.c index 08dba62..be9e896 100644 --- a/meshconsole/main.c +++ b/meshconsole/main.c @@ -68,6 +68,9 @@ void BreakSink(int s) if (agentHost != NULL) { MeshAgent_Stop(agentHost); } } #endif +#include +#include +#include #if defined(_LINKVM) && defined(__APPLE__) extern void* kvm_server_mainloop(void *parm); @@ -79,6 +82,246 @@ ILibTransport_DoneState kvm_serviceWriteSink(char *buffer, int bufferLen, void * } #endif +typedef int(*GdipLoadImageFromStream_func)(IStream* stream, void **image); +typedef int(*GdiplusStartup_func)(ULONG_PTR *token, void *input, void *output); +typedef int(*GdipSaveImageToStream_func)(void *image, IStream* stream, void* clsidEncoder, void* encoderParams); +typedef int(*GetImageEncodersSize_func)(UINT *numEncoders, UINT *size); +typedef int(*GetImageEncoders_func)(UINT numEncoders, UINT size, void *encoders); + +GetImageEncoders_func _GetImageEncoders = NULL; +GetImageEncodersSize_func _GetImageEncodersSize = NULL; +GdipLoadImageFromStream_func _GdipLoadImageFromStream = NULL; +GdiplusStartup_func _GdiplusStartup = NULL; +GdipSaveImageToStream_func _GdipSaveImageToStream = NULL; + +typedef HRESULT(*D3D11CreateDevice_func)(void *pAdapter, int DriverType, HMODULE Software, UINT Flags, int *pFeatureLevels, UINT FeatureLevels, UINT SDKVersion, void **ppDevice, UINT *pFeatureLevel, void **context); +typedef HRESULT(*GetParent_func)(void *self, void* iid, void **ppParent); +typedef ULONG(*Release_func)(void *self); +typedef UINT(*D3D11CalcSubresource_func)(UINT MipSlice, UINT ArraySlice, UINT MipLevels); + +UINT defaultCompressionLevel = 50; +DWORD tilebuffersize = 0; +LPVOID tilebuffer = NULL; +int SCALED_WIDTH, SCREEN_WIDTH; +int SCALED_HEIGHT, SCREEN_HEIGHT; + +extern void __jpeghelp2(void *x); +// Used to obtain the GUID for the image encoder. +int GetEncoderClsid(const WCHAR* format, CLSID* pClsid) +{ + unsigned int num = 0, size = 0; + char* pImageCodecInfo = NULL; + + _GetImageEncodersSize(&num, &size); + if (size == 0) return -1; + + if ((pImageCodecInfo = (char*)(malloc(size))) == NULL) return -1; + _GetImageEncoders(num, size, (void*)pImageCodecInfo); + + for (unsigned int j = 0; j < num; ++j) + { + WCHAR *tmp = ((WCHAR**)(pImageCodecInfo + (104 * j) + 64))[0]; + if (wcsncmp(tmp, format, size) == 0) + { + *pClsid = ((CLSID*)(pImageCodecInfo + (104 * j)))[0]; + free(pImageCodecInfo); + return j; + } + } + + free(pImageCodecInfo); + return -1; +} + +// Adjusts the screen size(width or height) to be exactly divisible by TILE_WIDTH +int adjust_screen_size(int pixles) +{ + int extra = pixles % 32; // Assuming tile width and height will remain the same. + if (extra != 0) return pixles + 32 - extra; + return pixles; +} + +// Creates a BITMAPINFO object with required width and height +BITMAPINFO _get_bmp_info(int width, int height, int PIXEL_SIZE) +{ + BITMAPINFO bmpInfo; + + ZeroMemory(&bmpInfo, sizeof(BITMAPINFO)); + bmpInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); + bmpInfo.bmiHeader.biBitCount = (WORD)(PIXEL_SIZE * 8); + bmpInfo.bmiHeader.biSize = 40; + bmpInfo.bmiHeader.biHeight = height; + bmpInfo.bmiHeader.biWidth = width; + bmpInfo.bmiHeader.biSizeImage = height * width * PIXEL_SIZE; + bmpInfo.bmiHeader.biPlanes = 1; + + return bmpInfo; +} +// Extracts the required tile buffer from the desktop buffer +int _get_tile_buffer(int x, int y, int PIXEL_SIZE, void **buffer, void *desktop, int tilewidth, int tileheight) +{ + void *target = *buffer; + for (int height = adjust_screen_size(SCALED_HEIGHT) - y - tileheight; height < adjust_screen_size(SCALED_HEIGHT) - y; height++) + { + memcpy_s(target, tilebuffersize, (const void *)((unsigned char *)desktop + (((height * adjust_screen_size(SCALED_WIDTH)) + x) * PIXEL_SIZE)), (size_t)(tilewidth * PIXEL_SIZE)); + target = (void *)((unsigned char *)target + tilewidth * PIXEL_SIZE); + } + return 0; +} + +int _calc_opt_compr_send(int x, int y, int PIXEL_SIZE, int captureWidth, int captureHeight, void* desktop, void ** buffer, int64_t *bufferSize) +{ + BITMAPINFO bmpInfo; + LARGE_INTEGER Offset; + BITMAPFILEHEADER bmpFileHeader; + *buffer = NULL; + *bufferSize = 0; + + // Get the bmpInfo structure + bmpInfo = _get_bmp_info(captureWidth, captureHeight, PIXEL_SIZE); + + // Make sure a tile buffer is available. Most of the time, this is skipped. + if (tilebuffersize != bmpInfo.bmiHeader.biSizeImage) + { + if (tilebuffer != NULL) free(tilebuffer); + tilebuffersize = bmpInfo.bmiHeader.biSizeImage; + if ((tilebuffer = malloc(tilebuffersize)) == NULL) return 0; + } + + // Get the final coalesced tile + _get_tile_buffer(x, y, PIXEL_SIZE, &tilebuffer, desktop, captureWidth, captureHeight); + + bmpFileHeader.bfReserved1 = 0; + bmpFileHeader.bfReserved2 = 0; + bmpFileHeader.bfSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + bmpInfo.bmiHeader.biSizeImage; + bmpFileHeader.bfType = 'MB'; + bmpFileHeader.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER); + + // Construct stream object. + IStream* bmpStream = NULL; + if (CreateStreamOnHGlobal(NULL, TRUE, (LPSTREAM*)&bmpStream) != S_OK) + { + ILibCriticalLog(NULL, __FILE__, __LINE__, 252, GetLastError()); + return 0; + } + + // Write entire contents of the source BMP into this stream. + bmpStream->lpVtbl->Write(bmpStream, &bmpFileHeader, sizeof(BITMAPFILEHEADER), NULL); + bmpStream->lpVtbl->Write(bmpStream, &bmpInfo, sizeof(BITMAPINFOHEADER), NULL); + bmpStream->lpVtbl->Write(bmpStream, tilebuffer, bmpInfo.bmiHeader.biSizeImage, NULL); + + // Move the stream pointer to the beginning of the stream. + Offset.QuadPart = 0; + if (bmpStream->lpVtbl->Seek(bmpStream, Offset, STREAM_SEEK_SET, NULL) != S_OK) + { + bmpStream->lpVtbl->Release(bmpStream); + ILibCriticalLog(NULL, __FILE__, __LINE__, 252, GetLastError()); + return 0; + } + + // Construct GDI+ Image object from the BMP stream. + void *DIBImage; + _GdipLoadImageFromStream(bmpStream, &DIBImage); + + // Create stream to receive the encoded JPEG. + IStream* jpegStream = NULL; + if (CreateStreamOnHGlobal(NULL, TRUE, (LPSTREAM*)&jpegStream) != S_OK) + { + //delete DIBImage; + bmpStream->lpVtbl->Release(bmpStream); + ILibCriticalLog(NULL, __FILE__, __LINE__, 252, GetLastError()); + return 0; + } + + CLSID encoderClsid; + GetEncoderClsid(L"image/jpeg", &encoderClsid); + + char encparms[40]; + ((uint32_t*)encparms)[0] = 1; // EncoderParameters::Count + util_hexToBuf("B5E45B1D4AFA2D459CDD5DB35105E7EB", 32, encparms + 8); // EncoderParameter::Guid + ((uint32_t*)(24 + encparms))[0] = 1; // EncoderParameter::NumberOfValues + ((uint32_t*)(28 + encparms))[0] = 4; // EncoderParameter::Type + ((void**)(32 + encparms))[0] = (void*)&defaultCompressionLevel; // EncoderParameter::Value + + + // Save image stream into the stream object. + int SaveStatus = _GdipSaveImageToStream(DIBImage, jpegStream, &encoderClsid, (void*)encparms); + if (SaveStatus != S_OK) + { + //delete DIBImage; + bmpStream->lpVtbl->Release(bmpStream); + jpegStream->lpVtbl->Release(jpegStream); + ILibCriticalLog(NULL, __FILE__, __LINE__, 252, GetLastError()); + return 0; + } + + // Get the size of the output stream + ULARGE_INTEGER Size; + Offset.QuadPart = 0; + if (jpegStream->lpVtbl->Seek(jpegStream, Offset, STREAM_SEEK_END, &Size) != S_OK) + { + //delete DIBImage; + bmpStream->lpVtbl->Release(bmpStream); + jpegStream->lpVtbl->Release(jpegStream); + ILibCriticalLog(NULL, __FILE__, __LINE__, 252, GetLastError()); + return 0; + } + + // Move the image stream's pointer to its beginning. + Offset.QuadPart = 0; + if (jpegStream->lpVtbl->Seek(jpegStream, Offset, STREAM_SEEK_SET, NULL) != S_OK) + { + //delete DIBImage; + bmpStream->lpVtbl->Release(bmpStream); + jpegStream->lpVtbl->Release(jpegStream); + ILibCriticalLog(NULL, __FILE__, __LINE__, 252, GetLastError()); + return 0; + } + + // Check if the tile is too large to send + DWORD jpegSize = (DWORD)Size.QuadPart; + + // Save the image stream in memory. + char* Tile = (char*)ILibMemory_Allocate(jpegSize > 65500 ? (jpegSize + 16) : (jpegSize + 8), 0, NULL, NULL); + if (jpegStream->lpVtbl->Read(jpegStream, Tile + (jpegSize > 65500 ? 16 : 8), jpegSize, NULL) != S_OK) + { + //delete DIBImage; + free(Tile); + bmpStream->lpVtbl->Release(bmpStream); + jpegStream->lpVtbl->Release(jpegStream); + ILibCriticalLog(NULL, __FILE__, __LINE__, 252, GetLastError()); + return 0; + } + + // Cleanup + //delete DIBImage; + bmpStream->lpVtbl->Release(bmpStream); + jpegStream->lpVtbl->Release(jpegStream); + + *buffer = (unsigned char*)Tile; + *bufferSize = jpegSize + (jpegSize > 65500 ? 16 : 8); + + //// Place the header + //if (jpegSize > 65500) + //{ + // ((unsigned short*)*buffer)[0] = (unsigned short)htons((unsigned short)MNG_JUMBO); // Write the type + // ((unsigned short*)*buffer)[1] = (unsigned short)htons((unsigned short)8); // Write the size + // ((unsigned int*)*buffer)[1] = (unsigned int)htonl(jpegSize + 8); // Size of the Next Packet + // ((unsigned short*)*buffer)[4] = (unsigned short)htons((unsigned short)MNG_KVM_PICTURE); // Write the type + // ((unsigned short*)*buffer)[5] = 0; // RESERVED + // ((unsigned short*)*buffer)[6] = (unsigned short)htons((unsigned short)x); // X position + // ((unsigned short*)*buffer)[7] = (unsigned short)htons((unsigned short)y); // Y position + //} + //else + //{ + // ((unsigned short*)*buffer)[0] = (unsigned short)htons((unsigned short)MNG_KVM_PICTURE); // Write the type + // ((unsigned short*)*buffer)[1] = (unsigned short)htons((unsigned short)*bufferSize); // Write the size + // ((unsigned short*)*buffer)[2] = (unsigned short)htons((unsigned short)x); // X position + // ((unsigned short*)*buffer)[3] = (unsigned short)htons((unsigned short)y); // Y position + //} + //return 0; +} +extern void __jpeghelp(void *x); #ifdef WIN32 #define wmain_free(argv) for(argvi=0;argvi<(int)(ILibMemory_Size(argv)/sizeof(void*));++argvi){ILibMemory_Free(argv[argvi]);}ILibMemory_Free(argv); int wmain(int argc, char **wargv) @@ -95,6 +338,269 @@ int main(int argc, char **argv) int integratedJavaScriptLen = 0; int retCode = 0; int capabilities = 0; + + CLSID encoderClsid; + HRESULT hr; + HMODULE GDIP = LoadLibraryExW(L"Gdiplus.dll", NULL, LOAD_LIBRARY_SEARCH_SYSTEM32); + void *gdiptoken = NULL; + char gdipinput[24] = { 0 }; + ((int*)gdipinput)[0] = 1; + + _GdipLoadImageFromStream = (GdipLoadImageFromStream_func)GetProcAddress(GDIP, "GdipLoadImageFromStream"); + _GdiplusStartup = (GdiplusStartup_func)GetProcAddress(GDIP, "GdiplusStartup"); + _GdipSaveImageToStream = (GdipSaveImageToStream_func)GetProcAddress(GDIP, "GdipSaveImageToStream"); + _GetImageEncodersSize = (GetImageEncodersSize_func)GetProcAddress(GDIP, "GdipGetImageEncodersSize"); + _GetImageEncoders = (GetImageEncoders_func)GetProcAddress(GDIP, "GdipGetImageEncoders"); + _GdiplusStartup(&gdiptoken, gdipinput, NULL); + + util_hexToBuf("B5E45B1D4AFA2D459CDD5DB35105E7EB", 32, ILibScratchPad); + + GUID G; + util_hexToBuf("B5E45B1D4AFA2D459CDD5DB35105E7EB", 32, &G); + + char encparms[40]; + + + //EncoderParameters::Count = > 0 + //EncoderParameters::Parameter = > 8 + //EncoderParameter::Guid = > 0 + //EncoderParameter::NumberOfValues = > 16 + //EncoderParameter::Type = > 20 + //EncoderParameter::Value = > 24 + + + HMODULE D3D = LoadLibraryExW(L"D3D11.dll", NULL, LOAD_LIBRARY_SEARCH_SYSTEM32); + D3D11CreateDevice_func func = (D3D11CreateDevice_func)GetProcAddress(D3D, "D3D11CreateDevice"); + D3D11CalcSubresource_func func2 = (D3D11CalcSubresource_func)GetProcAddress(D3D, "D3D11CalcSubresource"); + + void *lDevice = NULL; + int lFeatureLevel = 0; + ID3D11DeviceContext *lImmediateContext = NULL; + + IID iid; + hr = IIDFromString(L"{54ec77fa-1377-44e6-8c32-88fd5f44c84c}", &iid); + + // Create device + UINT gNumDriverTypes = 1; + for (UINT DriverTypeIndex = 0; DriverTypeIndex < gNumDriverTypes; ++DriverTypeIndex) + { + hr = func(NULL, D3D_DRIVER_TYPE_HARDWARE, NULL, 0, NULL, 0, D3D11_SDK_VERSION, &lDevice, &lFeatureLevel, &lImmediateContext); + + if (SUCCEEDED(hr)) + { + // Device creation success, no need to loop anymore + break; + } + ((ID3D11Device*)lDevice)->lpVtbl->Release(lDevice); + ((ID3D11DeviceContext*)lImmediateContext)->lpVtbl->Release(lImmediateContext); + } + + // Get DXGI device + IDXGIDevice *lDxgiDevice; + hr = ((ID3D11Device*)lDevice)->lpVtbl->QueryInterface(lDevice, &iid, &lDxgiDevice); + + // Get DXGI adapter + GetParent_func fnc = (GetParent_func)((void**)((void**)lDxgiDevice)[0])[6]; // GetParent + IID adapteriid; + void *adapter = NULL; + IIDFromString(L"{2411e7e1-12ac-4ccf-bd14-9798e8534dc0}", &adapteriid); + hr = fnc(lDxgiDevice, &adapteriid, &adapter); + + ((Release_func)((void**)((void**)lDxgiDevice)[0])[2])(lDxgiDevice); // Release + UINT Output = 0; + IDXGIOutput *lDxgiOutput = NULL; + hr = ((IDXGIAdapter*)adapter)->lpVtbl->EnumOutputs(adapter, Output, &lDxgiOutput); // Get output + ((IDXGIAdapter*)adapter)->lpVtbl->Release(adapter); + + DXGI_OUTPUT_DESC outdesc; + hr = lDxgiOutput->lpVtbl->GetDesc(lDxgiOutput, &outdesc); + + IID output1IID; + IDXGIOutput1 *output1 = NULL; + IIDFromString(L"{00cddea8-939b-4b83-a340-a685226666cc}", &output1IID); + hr = lDxgiOutput->lpVtbl->QueryInterface(lDxgiOutput, &output1IID, &output1); + + lDxgiOutput->lpVtbl->Release(lDxgiOutput); + + IDXGIOutputDuplication *lDeskDupl = NULL; + + // Create desktop duplication + hr = output1->lpVtbl->DuplicateOutput(output1, lDevice, &lDeskDupl); + lDxgiOutput->lpVtbl->Release(lDxgiOutput); + + // Create GUI drawing texture + DXGI_OUTDUPL_DESC lOutputDuplDesc; + lDeskDupl->lpVtbl->GetDesc(lDeskDupl, &lOutputDuplDesc); + + D3D11_TEXTURE2D_DESC desc; + ID3D11Texture2D *lGDIImage = NULL; + ID3D11Texture2D *lDestImage = NULL; + ID3D11Texture2D *lAcquiredDesktopImage = NULL; + + desc.Width = lOutputDuplDesc.ModeDesc.Width; + desc.Height = lOutputDuplDesc.ModeDesc.Height; + desc.Format = lOutputDuplDesc.ModeDesc.Format; + desc.ArraySize = 1; + desc.BindFlags = D3D11_BIND_RENDER_TARGET; + desc.MiscFlags = D3D11_RESOURCE_MISC_GDI_COMPATIBLE; + desc.SampleDesc.Count = 1; + desc.SampleDesc.Quality = 0; + desc.MipLevels = 1; + desc.CPUAccessFlags = 0; + desc.Usage = D3D11_USAGE_DEFAULT; + hr = ((ID3D11Device*)lDevice)->lpVtbl->CreateTexture2D(lDevice, &desc, NULL, &lGDIImage); + + + // Create CPU access texture + desc.Width = lOutputDuplDesc.ModeDesc.Width; + desc.Height = lOutputDuplDesc.ModeDesc.Height; + desc.Format = lOutputDuplDesc.ModeDesc.Format; + desc.ArraySize = 1; + desc.BindFlags = 0; + desc.MiscFlags = 0; + desc.SampleDesc.Count = 1; + desc.SampleDesc.Quality = 0; + desc.MipLevels = 1; + desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE; + desc.Usage = D3D11_USAGE_STAGING; + hr = ((ID3D11Device*)lDevice)->lpVtbl->CreateTexture2D(lDevice, &desc, NULL, &lDestImage); + + IDXGIResource *lDesktopResource; + DXGI_OUTDUPL_FRAME_INFO lFrameInfo; + int lTryCount = 4; + + do + { + + Sleep(100); + + // Get new frame + hr = lDeskDupl->lpVtbl->AcquireNextFrame( + lDeskDupl, + 250, + &lFrameInfo, + &lDesktopResource); + + if (SUCCEEDED(hr)) + break; + + if (hr == DXGI_ERROR_WAIT_TIMEOUT) + { + continue; + } + else if (FAILED(hr)) + break; + + } while (--lTryCount > 0); + + IID ID3D11Texture2D_IID; + IIDFromString(L"{6f15aaf2-d208-4e89-9ab4-489535d34f9c}", &ID3D11Texture2D_IID); + hr = lDesktopResource->lpVtbl->QueryInterface(lDesktopResource, &ID3D11Texture2D_IID, &lAcquiredDesktopImage); + lDesktopResource->lpVtbl->Release(lDesktopResource); + + // Copy image into GDI drawing texture + lImmediateContext->lpVtbl->CopyResource(lImmediateContext, lGDIImage, lAcquiredDesktopImage); + + + // Draw cursor image into GDI drawing texture + IID IDXGISurface1_IID; + IIDFromString(L"{4AE63092-6327-4c1b-80AE-BFE12EA32B86}", &IDXGISurface1_IID); + IDXGISurface1 *lIDXGISurface1 = NULL; + hr = lGDIImage->lpVtbl->QueryInterface(lGDIImage, &IDXGISurface1_IID, &lIDXGISurface1); + + CURSORINFO lCursorInfo = { 0 }; + lCursorInfo.cbSize = sizeof(lCursorInfo); + + if (GetCursorInfo(&lCursorInfo) == TRUE) + { + if (lCursorInfo.flags == CURSOR_SHOWING) + { + POINT lCursorPosition = lCursorInfo.ptScreenPos; + DWORD lCursorSize = lCursorInfo.cbSize; + HDC lHDC; + + lIDXGISurface1->lpVtbl->GetDC(lIDXGISurface1, FALSE, &lHDC); + + DrawIconEx( + lHDC, + lCursorPosition.x, + lCursorPosition.y, + lCursorInfo.hCursor, + 0, + 0, + 0, + 0, + DI_NORMAL | DI_DEFAULTSIZE); + + lIDXGISurface1->lpVtbl->ReleaseDC(lIDXGISurface1, NULL); + } + } + + // Copy image into CPU access texture + lImmediateContext->lpVtbl->CopyResource(lImmediateContext, lDestImage, lGDIImage); + + // Copy from CPU access texture to bitmap buffer + D3D11_MAPPED_SUBRESOURCE resource; + UINT subresource = 0; + lImmediateContext->lpVtbl->Map(lImmediateContext, lDestImage, subresource, D3D11_MAP_READ_WRITE, 0, &resource); + + BITMAPINFO lBmpInfo; + ZeroMemory(&lBmpInfo, sizeof(BITMAPINFO)); + lBmpInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); + lBmpInfo.bmiHeader.biBitCount = 32; + lBmpInfo.bmiHeader.biCompression = BI_RGB; + lBmpInfo.bmiHeader.biWidth = lOutputDuplDesc.ModeDesc.Width; + lBmpInfo.bmiHeader.biHeight = lOutputDuplDesc.ModeDesc.Height; + lBmpInfo.bmiHeader.biPlanes = 1; + lBmpInfo.bmiHeader.biSizeImage = lOutputDuplDesc.ModeDesc.Width * lOutputDuplDesc.ModeDesc.Height * 4; + + BYTE* pBuf; + ILibMemory_AllocateRaw(pBuf, lBmpInfo.bmiHeader.biSizeImage); + UINT lBmpRowPitch = lOutputDuplDesc.ModeDesc.Width * 4; + BYTE* sptr = (BYTE*)resource.pData; + BYTE* dptr = pBuf + lBmpInfo.bmiHeader.biSizeImage - lBmpRowPitch; + UINT lRowPitch = ((lBmpRowPitch < resource.RowPitch) ? lBmpRowPitch : resource.RowPitch); + + for (size_t h = 0; h < lOutputDuplDesc.ModeDesc.Height; ++h) + { + memcpy_s(dptr, lBmpRowPitch, sptr, lRowPitch); + sptr += resource.RowPitch; + dptr -= lBmpRowPitch; + } + + char *desk = NULL; + int64_t deskSize = 0; + int vv = _calc_opt_compr_send(0, 0, 4, lOutputDuplDesc.ModeDesc.Width, lOutputDuplDesc.ModeDesc.Height, pBuf, &desk, &deskSize); + + + + // Save bitmap buffer into the file ScreenShot.bmp + FILE* lfile = NULL; + errno_t lerr = _wfopen_s(&lfile, L"C:\\TEST\\KVM.bmp", L"wb"); + + if (lfile != NULL) + { + + BITMAPFILEHEADER bmpFileHeader; + + bmpFileHeader.bfReserved1 = 0; + bmpFileHeader.bfReserved2 = 0; + bmpFileHeader.bfSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + lBmpInfo.bmiHeader.biSizeImage; + bmpFileHeader.bfType = 'MB'; + bmpFileHeader.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER); + + fwrite(&bmpFileHeader, sizeof(BITMAPFILEHEADER), 1, lfile); + fwrite(&lBmpInfo.bmiHeader, sizeof(BITMAPINFOHEADER), 1, lfile); + fwrite(pBuf, lBmpInfo.bmiHeader.biSizeImage, 1, lfile); + + fclose(lfile); + } + + + + + + #ifdef WIN32 int argvi, argvsz; diff --git a/meshcore/KVM/Windows/tile.cpp b/meshcore/KVM/Windows/tile.cpp index 4cafd8d..ea377b7 100644 --- a/meshcore/KVM/Windows/tile.cpp +++ b/meshcore/KVM/Windows/tile.cpp @@ -75,6 +75,34 @@ EncoderParameters encParam; LPVOID tilebuffer = NULL; unsigned int tilebuffersize = 0; +extern "C" +{ + void __jpeghelp(void *xx) + { + EncoderParameters *pp = (EncoderParameters*)xx; + GUID x = EncoderQuality; + printf("ImageCodecInfo: %d", sizeof(ImageCodecInfo)); + printf("MimeType: %d\n", FIELD_OFFSET(ImageCodecInfo, MimeType)); + printf("Clsid: %d\n", FIELD_OFFSET(ImageCodecInfo, Clsid)); + printf("EncoderParameters::Count => %d\n", FIELD_OFFSET(EncoderParameters, Count)); + printf("EncoderParameters::Parameter => %d\n", FIELD_OFFSET(EncoderParameters, Parameter)); + printf("EncoderParameter::Guid => %d\n", FIELD_OFFSET(EncoderParameter, Guid)); + printf("EncoderParameter::NumberOfValues => %d\n", FIELD_OFFSET(EncoderParameter, NumberOfValues)); + printf("EncoderParameter::Type => %d\n", FIELD_OFFSET(EncoderParameter, Type)); + printf("EncoderParameter::Value => %d\n", FIELD_OFFSET(EncoderParameter, Value)); + printf("sizeof(EncoderParameters): %d\n", sizeof(EncoderParameters)); + } + void __jpeghelp2(void *x) + { + ImageCodecInfo *info = (ImageCodecInfo*)x; + printf("MIME: %d\n", (char*)&(info->MimeType) - (char*)info); + if (info != NULL) + { + printf("x"); + } + } +} + // Used to obtain the GUID for the image encoder. int GetEncoderClsid(const WCHAR* format, CLSID* pClsid) { diff --git a/meshcore/agentcore.c b/meshcore/agentcore.c index 3ae06cd..fe691f8 100644 --- a/meshcore/agentcore.c +++ b/meshcore/agentcore.c @@ -2182,10 +2182,6 @@ int agent_GenerateCertificates(MeshAgentHostContainer *agent, char* certfile) return 0; } -void agent_LoadCertificates_DB_Check(ILibSimpleDataStore sender, char* Key, int KeyLen, void *user) -{ - ((size_t*)user)[0] += 1; -} int agent_LoadCertificates(MeshAgentHostContainer *agent) { int len; @@ -2270,11 +2266,7 @@ int agent_LoadCertificates(MeshAgentHostContainer *agent) } } #endif - - size_t keycount = 0; - ILibSimpleDataStore_EnumerateKeys(agent->masterDb, agent_LoadCertificates_DB_Check, &keycount); - - if (keycount > 1) + if(ILibSimpleDataStore_WasCreatedAsNew(agent->masterDb)==0) { // No certificate in the database. Return 1 here so we can generate one. ILibRemoteLogging_printf(ILibChainGetLogger(agent->chain), ILibRemoteLogging_Modules_Agent_GuardPost, ILibRemoteLogging_Flags_VerbosityLevel_1, "...Failed to load Node Certificate from Database"); diff --git a/microstack/ILibSimpleDataStore.c b/microstack/ILibSimpleDataStore.c index 9d46556..622c01c 100644 --- a/microstack/ILibSimpleDataStore.c +++ b/microstack/ILibSimpleDataStore.c @@ -54,6 +54,7 @@ typedef struct ILibSimpleDataStore_Root ILibSimpleDataStore_SizeWarningHandler warningSink; void* warningSinkUser; int error; + int createdAsNew; ILibSimpleDataStore_WriteErrorHandler ErrorHandler; void *ErrorHandlerUser; } ILibSimpleDataStore_Root; @@ -503,9 +504,10 @@ void ILibSimpleDataStore_RebuildKeyTable(ILibSimpleDataStore_Root *root) } // Open the data store file -FILE* ILibSimpleDataStore_OpenFileEx2(char* filePath, int forceTruncateIfNonZero, int readonly) +FILE* ILibSimpleDataStore_OpenFileEx3(char* filePath, int forceTruncateIfNonZero, int readonly, int *created) { FILE* f = NULL; + if (created != NULL) { *created = 0; } #ifdef WIN32 if (readonly == 0) @@ -516,6 +518,7 @@ FILE* ILibSimpleDataStore_OpenFileEx2(char* filePath, int forceTruncateIfNonZero h = CreateFileW(ILibUTF8ToWide(filePath, -1), GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, NULL, TRUNCATE_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (h == INVALID_HANDLE_VALUE && GetLastError() == ERROR_FILE_NOT_FOUND) { + if (created != NULL) { *created = 1; } h = CreateFileW(ILibUTF8ToWide(filePath, -1), GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL); } } @@ -524,6 +527,7 @@ FILE* ILibSimpleDataStore_OpenFileEx2(char* filePath, int forceTruncateIfNonZero h = CreateFileW(ILibUTF8ToWide(filePath, -1), GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (h == INVALID_HANDLE_VALUE && GetLastError() == ERROR_FILE_NOT_FOUND) { + if (created != NULL) { *created = 1; } h = CreateFileW(ILibUTF8ToWide(filePath, -1), GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL); } } @@ -546,6 +550,7 @@ FILE* ILibSimpleDataStore_OpenFileEx2(char* filePath, int forceTruncateIfNonZero if (forceTruncateIfNonZero != 0 || (f = fopen(filePath, flag)) == NULL) { + if (created != NULL) { *created = 1; } f = fopen(filePath, "wb+"); } if (f == NULL) { return NULL; } // If we failed to open the file, stop now. @@ -556,6 +561,7 @@ FILE* ILibSimpleDataStore_OpenFileEx2(char* filePath, int forceTruncateIfNonZero } #define ILibSimpleDataStore_OpenFile(filePath) ILibSimpleDataStore_OpenFileEx2(filePath, 0, 0) #define ILibSimpleDataStore_OpenFileEx(filePath, forceTruncate) ILibSimpleDataStore_OpenFileEx2(filePath, forceTruncate, 0) +#define ILibSimpleDataStore_OpenFileEx2(filePath, forceTruncate, readonly) ILibSimpleDataStore_OpenFileEx3(filePath, forceTruncate, readonly, NULL) int ILibSimpleDataStore_Exists(char *filePath) { #ifdef WIN32 @@ -568,11 +574,11 @@ int ILibSimpleDataStore_Exists(char *filePath) __EXPORT_TYPE ILibSimpleDataStore ILibSimpleDataStore_CreateEx2(char* filePath, int userExtraMemorySize, int readonly) { ILibSimpleDataStore_Root* retVal = (ILibSimpleDataStore_Root*)ILibMemory_Allocate(ILibMemory_SimpleDataStore_CONTAINERSIZE, userExtraMemorySize, NULL, NULL); - + if (filePath != NULL) { retVal->filePath = ILibString_Copy(filePath, strnlen_s(filePath, ILibSimpleDataStore_MaxFilePath)); - retVal->dataFile = ILibSimpleDataStore_OpenFileEx2(retVal->filePath, 0, readonly); + retVal->dataFile = ILibSimpleDataStore_OpenFileEx3(retVal->filePath, 0, readonly, &(retVal->createdAsNew)); if (retVal->dataFile == NULL) { @@ -1122,4 +1128,8 @@ __EXPORT_TYPE int ILibSimpleDataStore_Compact(ILibSimpleDataStore dataStore) int ILibSimpleDataStore_IsCacheOnly(ILibSimpleDataStore ds) { return(((ILibSimpleDataStore_Root*)ds)->dataFile == NULL ? 1 : 0); +} +int ILibSimpleDataStore_WasCreatedAsNew(ILibSimpleDataStore ds) +{ + return(((ILibSimpleDataStore_Root*)ds)->createdAsNew); } \ No newline at end of file diff --git a/microstack/ILibSimpleDataStore.h b/microstack/ILibSimpleDataStore.h index e9c3047..30f097a 100644 --- a/microstack/ILibSimpleDataStore.h +++ b/microstack/ILibSimpleDataStore.h @@ -51,6 +51,7 @@ __EXPORT_TYPE ILibSimpleDataStore ILibSimpleDataStore_CreateEx2(char* filePath, #define ILibSimpleDataStore_CreateCachedOnly() ILibSimpleDataStore_Create(NULL) void ILibSimpleDataStore_ReOpenReadOnly(ILibSimpleDataStore dataStore, char* filePath); int ILibSimpleDataStore_IsCacheOnly(ILibSimpleDataStore ds); +int ILibSimpleDataStore_WasCreatedAsNew(ILibSimpleDataStore ds); // Check if the data store exists int ILibSimpleDataStore_Exists(char *filePath); diff --git a/modules/awk-helper.js b/modules/awk-helper.js index 90420be..2335b92 100644 --- a/modules/awk-helper.js +++ b/modules/awk-helper.js @@ -15,7 +15,22 @@ limitations under the License. */ var child = { stdin: { str: '', write: function (v) { this.str += v.trim(); } } }; - +child.stdin.write("loginctl list-sessions | tr '\\n' '`' | awk '{"); +child.stdin.write('printf "[";'); +child.stdin.write('del="";'); +child.stdin.write('n=split($0, lines, "`");'); +child.stdin.write('for(i=1;i=1000)'); +child.stdin.write(' {'); +child.stdin.write(' if(tok[4]=="" || tok[4]~/^pts\\//) { continue; }'); +child.stdin.write(' printf "%s{\\"uid\\": \\"%s\\", \\"sid\\": \\"%s\\"}", del, tok[2], tok[1];'); +child.stdin.write(' del=",";'); +child.stdin.write(' }'); +child.stdin.write('}'); +child.stdin.write('printf "]";'); +child.stdin.write("}'"); //child.stdin.write('\nexit\n'); child.stdin.write('\n\n\n');