//+-------------------------------------------------------------------------- // // Microsoft Windows // Copyright (C) Microsoft Corporation, 2000 // // File: xmlwiz.cpp // // Contents: code for generating app matching XML // // History: ~12-Jan-00 dmunsil created // 18-Feb-00 dmunsil ver 0.8 -- added changing '&' to "&" // //--------------------------------------------------------------------------- #include "stdafx.h" #include "commdlg.h" #include "stdio.h" #include "assert.h" #include "xmlwizres.h" #include "verread.h" extern "C" { #include "shimdb.h" } #undef _GATHER_TIME #define MAX_LINE_LEN 500 #define MAX_NUM_LINES 100 #define MAX_TEXT_BUF 32768 #define MAX_WORKING_BUFFER_SIZE 65536 // Types typedef struct _MATCH_INFO { DWORD dwSize; DWORD dwChecksum; char szTime[20]; LARGE_INTEGER liBinFileVersion; LARGE_INTEGER liBinProdVersion; char szProductName[50]; } MATCH_INFO, *PMATCH_INFO; // Global Variables: HINSTANCE g_hInst; // current instance HWND g_hMainDlg; char g_szExeName[260]; char g_szExeFullPath[1000]; char g_szParentExeName[260]; char g_szParentExeFullPath[1000]; char g_szEditText[MAX_TEXT_BUF]; char g_aszEditLines[MAX_NUM_LINES][MAX_LINE_LEN]; UINT g_unEditLines; char g_szAppIndent[] = " "; // 4 spaces char g_szExeIndent[] = " "; // 8 spaces char g_szMatchIndent[] = " "; // 12 spaces char g_szMatchAttributeIndent[] = " "; // 27 spaces char g_szExeAttributeIndent[] = " "; // 13 spaces BOOL g_bSelectedParentExe = FALSE; DWORD g_dwSystemDlls = 0; HFONT g_hFont; // Foward declarations of functions included in this code module: ATOM MyRegisterClass(HINSTANCE hInstance); BOOL InitInstance(HINSTANCE, int); LRESULT CALLBACK DlgMain(HWND, UINT, WPARAM, LPARAM); LRESULT CALLBACK DlgDlls(HWND, UINT, WPARAM, LPARAM); void GetExeNames(HWND hDlg); void GetMatchFile(HWND hDlg); void UnpackEditLines(HWND hDlg); void PackEditLines(HWND hDlg); void DeleteLines(UINT unBegin, UINT unLen); void InsertLine(UINT unLine, char *szLine); void InsertExeLines(UINT unLine); BOOL bFindLine(char *szSearch, UINT *punLine); BOOL bFindLineFrom(char *szSearch, UINT unStart, UINT *punLine); void InitEditLines(void); void GetMatchInfo(char *szFile, PMATCH_INFO pMatch); DWORD GetFileChecksum(HANDLE handle); char *szGetRelativePath(char *pExeFile, char *pMatchFile); BOOL bSameDrive(char *szPath1, char *szPath2); void MySelectAll(HWND hDlg); void vEnumerateSystemDlls(HWND hDlg); void vAddSelectedDlls(HWND hDlg); void vWriteSysTest(void); char *szConvertSpecialChars(char *szString); int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { MSG msg; HACCEL hAccel; // Perform application initialization: if (!InitInstance (hInstance, nCmdShow)) { return FALSE; } hAccel = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDR_ACCELERATOR1)); if (hAccel == NULL) { return FALSE; } g_hMainDlg = CreateDialog(hInstance, (LPCTSTR)IDD_MAIN, NULL, (DLGPROC)DlgMain); // Main message loop: while (GetMessage(&msg, NULL, 0, 0)) { if (!TranslateAccelerator(g_hMainDlg, hAccel, &msg)) { TranslateMessage(&msg); DispatchMessage(&msg); } } return msg.wParam; } // // FUNCTION: InitInstance(HANDLE, int) // // PURPOSE: Saves instance handle and creates main window // // COMMENTS: // // In this function, we save the instance handle in a global variable and // create and display the main program window. // BOOL InitInstance(HINSTANCE hInstance, int nCmdShow) { //HWND hWnd; g_hInst = hInstance; // Store instance handle in our global variable g_szExeName[0] = '\0'; g_szExeFullPath[0] = '\0'; g_szParentExeName[0] = '\0'; g_szParentExeFullPath[0] = '\0'; InitEditLines(); return TRUE; } // Message handler for DLL dialog. LRESULT CALLBACK DlgDlls(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) { switch (message) { case WM_INITDIALOG: vEnumerateSystemDlls(hDlg); return TRUE; break; case WM_COMMAND: switch LOWORD(wParam) { case IDOK: vAddSelectedDlls(hDlg); // falls through case IDCANCEL: EndDialog(hDlg, LOWORD(wParam)); return TRUE; break; } } return FALSE; } // Message handler for main dialog. LRESULT CALLBACK DlgMain(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) { HDC hDC; switch (message) { case WM_INITDIALOG: if (!g_szExeName[0]) { HWND hBtn; hBtn = GetDlgItem(hDlg, IDC_BTN_ADD_MATCH); EnableWindow(hBtn, FALSE); hBtn = GetDlgItem(hDlg, IDC_BTN_ADD_DLL); EnableWindow(hBtn, FALSE); } // set the edit window to fixed-width font hDC = GetDC(hDlg); if (hDC) { g_hFont = CreateFont( -MulDiv(9, GetDeviceCaps(hDC, LOGPIXELSY), 72), // 9-pt font 0, 0, 0, FW_REGULAR, FALSE, FALSE, FALSE, ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, ANTIALIASED_QUALITY, FIXED_PITCH | FF_MODERN, NULL); if (g_hFont) { HWND hEdit = GetDlgItem(hDlg, IDC_EDIT1); SendMessage(hEdit, WM_SETFONT, (WPARAM)g_hFont, TRUE); } ReleaseDC(hDlg, hDC); } return TRUE; break; case WM_COMMAND: switch LOWORD(wParam) { case IDA_SELECT_ALL: MySelectAll(hDlg); break; case IDC_BTN_SET_EXE: GetExeNames(hDlg); break; case IDC_BTN_ADD_MATCH: GetMatchFile(hDlg); break; case IDC_BTN_ADD_DLL: DialogBox(g_hInst, (LPCTSTR)IDD_DLL_LIST, hDlg, (DLGPROC)DlgDlls); break; case IDC_BTN_WRITE_SYSTEST: vWriteSysTest(); break; case IDOK: case IDCANCEL: EndDialog(hDlg, LOWORD(wParam)); PostQuitMessage(0); DeleteObject(g_hFont); return TRUE; break; } } return FALSE; } void GetMatchFile(HWND hDlg) { OPENFILENAME ofn; MATCH_INFO MatchInfo; char szMatchFile[1000]; char szInitialPath[1000]; char szFileTitle[260]; char szDrive[_MAX_DRIVE]; char szDir[_MAX_DIR]; UINT unLine; char szTemp[MAX_LINE_LEN]; char szTime[MAX_LINE_LEN]; char szProdVer[MAX_LINE_LEN]; char szFileVer[MAX_LINE_LEN]; char szProdName[MAX_LINE_LEN]; char *szMatch; szMatchFile[0] = '\0'; szFileTitle[0] = '\0'; szInitialPath[0] = '\0'; if (g_szParentExeFullPath[0]) { _splitpath(g_szParentExeFullPath, szDrive, szDir, NULL, NULL); strcpy(szInitialPath, szDrive); strcat(szInitialPath, szDir); } ZeroMemory(&ofn, sizeof(OPENFILENAME)); ofn.lStructSize = sizeof(OPENFILENAME); ofn.hwndOwner = hDlg; ofn.lpstrFile = szMatchFile; ofn.nMaxFile = sizeof(szMatchFile); ofn.lpstrFilter = "All\0*.*\0Exe\0*.EXE\0"; ofn.nFilterIndex = 1; ofn.lpstrFileTitle = szFileTitle; ofn.nMaxFileTitle = sizeof(szFileTitle); ofn.lpstrInitialDir = szInitialPath; ofn.lpstrTitle = "Select Matching File"; ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST | OFN_NODEREFERENCELINKS; // get the matching file name if (GetOpenFileName(&ofn) == FALSE) { goto err1; } // get the lines out of the edit dialog UnpackEditLines(hDlg); // check if we need to get an parent exe if (!bSameDrive(szMatchFile, g_szParentExeFullPath) && !g_bSelectedParentExe) { char szParentFile[1000]; // get the parent exe szParentFile[0] = '\0'; szInitialPath[0] = '\0'; if (szMatchFile[0]) { _splitpath(szMatchFile, szDrive, szDir, NULL, NULL); strcpy(szInitialPath, szDrive); strcat(szInitialPath, szDir); } // most of ofn is already filled-in ofn.lpstrTitle = "Select Parent Exe"; ofn.lpstrFile = szParentFile; ofn.nMaxFile = sizeof(szParentFile); if (GetOpenFileName(&ofn) == TRUE) { strcpy(g_szParentExeName, szFileTitle); strcpy(g_szParentExeFullPath, szParentFile); g_bSelectedParentExe = TRUE; // delete any previous parent exe comments while (bFindLine("", g_szMatchIndent, szPathWithoutDrive); } else { sprintf(szTemp, "%s", g_szMatchIndent, szPathWithoutDrive); } if (bFindLine("", unLine, &unLine)) { InsertLine(unLine + 1, szTemp); } } } } } // check the drive letters to see which drive the match file is on // then calculate a relative path to the matching file if (bSameDrive(szMatchFile, g_szParentExeFullPath)) { szMatch = szGetRelativePath(g_szParentExeFullPath, szMatchFile); } else if (bSameDrive(szMatchFile, g_szExeFullPath)) { szMatch = szGetRelativePath(g_szExeFullPath, szMatchFile); } else { MessageBox(hDlg, "Match file is not on same drive as either EXE or Parent EXE. " "Can't generate relative path.", "Error", MB_ICONEXCLAMATION); goto err2; } // reconstruct the EXE if necessary if (!bFindLine(" or at the beginning if (!bFindLine(" line and insert if necessary if (!bFindLine("", &unLine)) { if (!bFindLine("", &unLine)) { unLine = g_unEditLines + 1; } sprintf(szTemp, "%s", g_szExeIndent); InsertLine(unLine, szTemp); } GetMatchInfo(szMatchFile, &MatchInfo); // now insert the line right before #ifdef _SPLIT_LINES sprintf(szTemp, "%s", g_szMatchIndent ); InsertLine(unLine++, szTemp); #else if (MatchInfo.szTime[0] != 0) { sprintf(szTime, " TIME=\"%s\"", MatchInfo.szTime); } else { szTime[0] = 0; } if (MatchInfo.liBinFileVersion.QuadPart) { sprintf(szFileVer, " BIN_FILE_VERSION=\"%d.%d.%d.%d\"", HIWORD(MatchInfo.liBinFileVersion.HighPart), LOWORD(MatchInfo.liBinFileVersion.HighPart), HIWORD(MatchInfo.liBinFileVersion.LowPart), LOWORD(MatchInfo.liBinFileVersion.LowPart)); } else { szFileVer[0] = 0; } if (MatchInfo.liBinProdVersion.QuadPart) { sprintf(szProdVer, " BIN_PRODUCT_VERSION=\"%d.%d.%d.%d\"", HIWORD(MatchInfo.liBinProdVersion.HighPart), LOWORD(MatchInfo.liBinProdVersion.HighPart), HIWORD(MatchInfo.liBinProdVersion.LowPart), LOWORD(MatchInfo.liBinProdVersion.LowPart)); } else { szProdVer[0] = 0; } if (MatchInfo.szProductName[0]) { sprintf(szProdName, " PRODUCT_NAME=\"%s\"", MatchInfo.szProductName); } else { szProdName[0] = 0; } sprintf(szTemp, "%s", g_szMatchIndent, szMatch, MatchInfo.dwSize, MatchInfo.dwChecksum, szTime, szFileVer, szProdVer, szProdName ); InsertLine(unLine, szTemp); #endif err2: // put them back into the dialog PackEditLines(hDlg); err1: return; } void GetExeNames(HWND hDlg) { OPENFILENAME ofn; char szFile[1000]; char szFileTitle[260]; HWND hBtn; char szTemp[MAX_LINE_LEN]; szFile[0] = '\0'; szFileTitle[0] = '\0'; ZeroMemory(&ofn, sizeof(OPENFILENAME)); ofn.lStructSize = sizeof(OPENFILENAME); ofn.hwndOwner = hDlg; ofn.lpstrFile = szFile; ofn.nMaxFile = sizeof(szFile); ofn.lpstrFilter = "All\0*.*\0Exe\0*.EXE\0"; ofn.nFilterIndex = 1; ofn.lpstrFileTitle = szFileTitle; ofn.nMaxFileTitle = sizeof(szFileTitle); ofn.lpstrInitialDir = NULL; ofn.lpstrTitle = "Select Exe to Shim"; ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST | OFN_NODEREFERENCELINKS; // get the main exe name if (GetOpenFileName(&ofn) == FALSE) { return; } strcpy(g_szExeName, szFileTitle); strcpy(g_szExeFullPath, szFile); // the parent exe defaults to the same as the EXE strcpy(g_szParentExeName, szFileTitle); strcpy(g_szParentExeFullPath, szFile); g_bSelectedParentExe = FALSE; // construct our new dialog text InitEditLines(); sprintf(szTemp, "%s", g_szAppIndent); InsertLine(0, szTemp); InsertExeLines(1); sprintf(szTemp, "%s", g_szExeIndent); InsertLine(999, szTemp); sprintf(szTemp, "%s", g_szAppIndent); InsertLine(999, szTemp); // stick it in the dialog box PackEditLines(hDlg); hBtn = GetDlgItem(hDlg, IDC_BTN_ADD_MATCH); EnableWindow(hBtn, TRUE); hBtn = GetDlgItem(hDlg, IDC_BTN_ADD_DLL); EnableWindow(hBtn, TRUE); } #define SECS_IN_DAY 86400 #define HUNDRED_NSECS_IN_SEC 10000000 void GetMatchInfo(char *szFile, PMATCH_INFO pMatch) { HANDLE hFile; FILETIME ft; SYSTEMTIME st; ZeroMemory(pMatch, sizeof(MATCH_INFO)); hFile = CreateFile( szFile, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (hFile != INVALID_HANDLE_VALUE ) { DWORD dwAttributes; pMatch->dwSize = GetFileSize(hFile, NULL); pMatch->dwChecksum = GetFileChecksum(hFile); pMatch->szTime[0] = 0; #ifdef _GATHER_TIME // only get the time if the file is not read only, and the date is // not within 2 days of today dwAttributes = GetFileAttributes(szFile); if (dwAttributes != -1 && (dwAttributes & FILE_ATTRIBUTE_READONLY)) { SYSTEMTIME stMachine; FILETIME ftMachine; DWORD dwDayFile; DWORD dwDayMachine; LARGE_INTEGER liFile; LARGE_INTEGER liMachine; LARGE_INTEGER liDifference; GetFileTime(hFile, &ft, NULL, NULL); FileTimeToSystemTime(&ft, &st); GetSystemTime(&stMachine); SystemTimeToFileTime(&stMachine, &ftMachine); liFile.LowPart = ft.dwLowDateTime; liFile.HighPart = ft.dwHighDateTime; liMachine.LowPart = ftMachine.dwLowDateTime; liMachine.HighPart = ftMachine.dwHighDateTime; liDifference.QuadPart = liMachine.QuadPart - liFile.QuadPart; // this goofy math is because I can't specify more than a 32-bit // value as a constant in this compiler if ((liDifference.QuadPart / HUNDRED_NSECS_IN_SEC) > SECS_IN_DAY * 2) { sprintf(pMatch->szTime, "%2.2d/%2.2d/%4.4d %2.2d:%2.2d:%2.2d", st.wMonth, st.wDay, st.wYear, st.wHour, st.wMinute, st.wSecond); } } #endif CloseHandle(hFile); // now get resource info VERSION_DATA VersionData; if (bInitVersionData(szFile, &VersionData)) { char *szProductName = NULL; pMatch->liBinFileVersion.QuadPart = qwGetBinFileVer(&VersionData); pMatch->liBinProdVersion.QuadPart = qwGetBinProdVer(&VersionData); #if 0 szProductName = szGetVersionString(&VersionData, "ProductName"); if (szProductName) { int nLen; nLen = sizeof(pMatch->szProductName) - 1; strncpy(pMatch->szProductName, szProductName, nLen); pMatch->szProductName[nLen] = 0; } #endif vReleaseVersionData(&VersionData); } } else { MessageBox(NULL, "Can't open match file for READ. Matching info inaccurate.", "Error", MB_ICONEXCLAMATION); pMatch->dwSize = 0; pMatch->dwChecksum = 0xDEADBEEF; pMatch->szTime[0] = 0; } } void InitEditLines(void) { g_unEditLines = 0; } void UnpackEditLines(HWND hDlg) { char *szTemp, *szBegin; GetDlgItemText(hDlg, IDC_EDIT1, g_szEditText, MAX_TEXT_BUF - 1); szBegin = g_szEditText; g_unEditLines = 0; if (!szBegin[0]) { return; } while (szTemp = strstr(szBegin, "\r\n")) { // temporarily terminate the string and copy *szTemp = '\0'; strcpy(g_aszEditLines[g_unEditLines], szBegin); g_unEditLines++; // back to normal *szTemp = '\r'; szBegin = szTemp + 2; } // copy in the final line, if any if (szBegin[0]) { strcpy(g_aszEditLines[g_unEditLines], szBegin); g_unEditLines++; } } void PackEditLines(HWND hDlg) { UINT i; char *szTemp = g_szEditText; HWND hEdit = GetDlgItem(hDlg, IDC_EDIT1); for (i = 0; i < g_unEditLines; ++i) { int nLen = strlen(g_aszEditLines[i]); memcpy(szTemp, g_aszEditLines[i], nLen); szTemp += nLen; memcpy(szTemp, "\r\n", 2 * sizeof(char)); szTemp += 2; } *szTemp = '\0'; SetDlgItemText(hDlg, IDC_EDIT1, g_szEditText); SendMessage(hEdit, EM_SETSEL, 0, -1); // select everything SetFocus(hEdit); } void MySelectAll(HWND hDlg) { HWND hEdit = GetDlgItem(hDlg, IDC_EDIT1); SendMessage(hEdit, EM_SETSEL, 0, -1); // select everything SetFocus(hEdit); } void DeleteLines(UINT unBegin, UINT unLen) { UINT unEnd = unBegin + unLen; if (unBegin > g_unEditLines) { return; } if (unEnd > g_unEditLines) { unEnd = g_unEditLines; } while (unEnd < g_unEditLines) { strcpy(g_aszEditLines[unBegin++], g_aszEditLines[unEnd++]); } g_unEditLines -= unLen; } void InsertLine(UINT unLine, char *szLine) { UINT unTemp; if (unLine > g_unEditLines) { unLine = g_unEditLines; } unTemp = g_unEditLines; while (unTemp != unLine) { strcpy(g_aszEditLines[unTemp], g_aszEditLines[unTemp - 1]); unTemp--; } strcpy(g_aszEditLines[unLine], szConvertSpecialChars(szLine)); g_unEditLines++; } void InsertExeLines(UINT unLine) { char szTemp[MAX_LINE_LEN]; MATCH_INFO MatchInfo; char szTime[MAX_LINE_LEN]; char szProdVer[MAX_LINE_LEN]; char szFileVer[MAX_LINE_LEN]; GetMatchInfo(g_szExeFullPath, &MatchInfo); #ifdef _SPLIT_LINES sprintf(szTemp, "%s", g_szExeIndent ); InsertLine(unLine++, szTemp); #else if (MatchInfo.szTime[0] != 0) { sprintf(szTime, " TIME=\"%s\"", MatchInfo.szTime); } else { szTime[0] = 0; } if (MatchInfo.liBinFileVersion.QuadPart) { sprintf(szFileVer, " BIN_FILE_VERSION=\"%d.%d.%d.%d\"", HIWORD(MatchInfo.liBinFileVersion.HighPart), LOWORD(MatchInfo.liBinFileVersion.HighPart), HIWORD(MatchInfo.liBinFileVersion.LowPart), LOWORD(MatchInfo.liBinFileVersion.LowPart)); } else { szFileVer[0] = 0; } if (MatchInfo.liBinProdVersion.QuadPart) { sprintf(szProdVer, " BIN_PRODUCT_VERSION=\"%d.%d.%d.%d\"", HIWORD(MatchInfo.liBinProdVersion.HighPart), LOWORD(MatchInfo.liBinProdVersion.HighPart), HIWORD(MatchInfo.liBinProdVersion.LowPart), LOWORD(MatchInfo.liBinProdVersion.LowPart)); } else { szProdVer[0] = 0; } sprintf(szTemp, "%s", g_szExeIndent, g_szExeName, MatchInfo.dwSize, MatchInfo.dwChecksum, szTime, szFileVer, szProdVer ); InsertLine(unLine, szTemp); #endif } BOOL bFindLine(char *szSearch, UINT *punLine) { UINT i; for (i = 0; i < g_unEditLines; ++i) { if (g_aszEditLines[i][0] && strstr(g_aszEditLines[i], szSearch)) { *punLine = i; return TRUE; } } return FALSE; } BOOL bFindLineFrom(char *szSearch, UINT unStart, UINT *punLine) { UINT i; for (i = unStart; i < g_unEditLines; ++i) { if (g_aszEditLines[i][0] && strstr(g_aszEditLines[i], szSearch)) { *punLine = i; return TRUE; } } return FALSE; } char *szGetRelativePath(char *pExeFile, char *pMatchFile) { int iLenp = 0; int iLenq = 0; //int index = 0; BOOL bCommonBegin = FALSE; // do the two paths have a common beginning char *p = NULL; char *q = NULL; // BUGBUG -- if you call this function twice in a row // without copying the result, the second call will overwrite // the first -- consider changing to a passed-in string // static char result[MAX_PATH] = { '\0' }; char *resultIdx = result; p = strchr(pExeFile, '\\'); q = strchr(pMatchFile, '\\'); while( p && q ) { iLenp = p - pExeFile; iLenq = q - pMatchFile; if ( iLenp != iLenq ) break; if ( !(_strnicmp(pExeFile, pMatchFile, iLenp) == 0) ) break; bCommonBegin = TRUE; pExeFile = p + 1; pMatchFile = q + 1; p = strchr(pExeFile, '\\'); q = strchr(pMatchFile, '\\'); } if (bCommonBegin) { while( p ) { strcpy(resultIdx, "..\\"); resultIdx = resultIdx + 3; pExeFile = p + 1; p = strchr(pExeFile, '\\'); } strcpy(resultIdx, pMatchFile); return result; } // the two paths don't have a common beginning, // and there is no relative path return NULL; } BOOL bSameDrive(char *szPath1, char *szPath2) { char szDrive1[256]; char szDrive2[256]; char *szTemp1, *szTemp2; BOOL bReturn = FALSE; assert(szPath1 && szPath1[0] && szPath2 && szPath2[0]); if (szPath1[1] != szPath2[1]) { // if the 2nd characters don't match, then one // is a DOS style path and the other is UNC, // and we're definitely not on the same drive goto out; } if (szPath1[1] == ':') { // these are both DOS-style paths if (szPath1[0] == szPath2[0]) { // if the first characters match, it's the same drive bReturn = TRUE; } goto out; } // now we're sure we have two UNC-style paths // skip past the "\\" szTemp1 = szPath1 + 2; szTemp2 = szPath2 + 2; // skip to the next '\' szTemp1 = strchr(szTemp1, '\\'); szTemp2 = strchr(szTemp2, '\\'); // if we didn't find another backslash, bail if (!szTemp1 || !szTemp2) { goto out; } // skip to the next '\' again szTemp1++; szTemp2++; szTemp1 = strchr(szTemp1, '\\'); szTemp2 = strchr(szTemp2, '\\'); // if we didn't find another backslash, bail if (!szTemp1 || !szTemp2) { goto out; } // are they different sizes? if (szTemp1 - szPath1 != szTemp2 - szPath2) { goto out; } // they're the same size, are they the same string? if (memcmp(szPath1, szPath2, szTemp1-szPath1) == 0) { bReturn = TRUE; } out: return bReturn; } #define CHECKSUM_SIZE 4096 #define CHECKSUM_OFFSET 512 #define CHECKSUM_BUFFER (CHECKSUM_SIZE+CHECKSUM_OFFSET) DWORD GetFileChecksum(HANDLE handle) { PBYTE pBuffer; DWORD dwCheckSum; DWORD dwBytesRead; DWORD dwReadSize; dwCheckSum = 0; dwReadSize = GetFileSize(handle, NULL); if ( dwReadSize > CHECKSUM_BUFFER ) { dwReadSize = CHECKSUM_BUFFER; } pBuffer = new BYTE[dwReadSize]; if ( !pBuffer ) { dwCheckSum = 0xDEADBEEF; goto err1; } SetFilePointer(handle, 0L, NULL, FILE_BEGIN); ZeroMemory(pBuffer, dwReadSize); // // We can get away with this since if the read fails then the check sum will also fail. // if ( !ReadFile(handle, (PBYTE)pBuffer, dwReadSize, &dwBytesRead, NULL) ) { dwCheckSum = 0xDEADBEEF; goto err2; } { INT i,size = CHECKSUM_SIZE; DWORD startAddr = CHECKSUM_OFFSET; PBYTE pTemp = pBuffer; if (dwBytesRead < (ULONG)size) { // // File size is less than 4096. We set the start address to 0 and set the size for the checksum // to the actual file size. // startAddr = 0; size = dwBytesRead; } else if (startAddr + size > dwBytesRead) { // // File size is too small. We set the start address so that size of checksum can be 4096 bytes // startAddr = dwBytesRead - size; } if (size < 4) { // // we need at least 4 bytes to be able to do something here. // dwCheckSum = 0; goto err2; } // start at the offset pTemp = pTemp + startAddr; // walk through adding in DWORDs and rotating the result to guard against // transposition for (i = 0; i < (size - 3); i += 4) { dwCheckSum += *((PDWORD) (pTemp + i)); dwCheckSum = _rotr (dwCheckSum, 1); } } err2: delete [] pBuffer; err1: return dwCheckSum; } void vWriteSysTest(void) { char szHeader[] = "\r\n\r\n"; char szTrailer[] = "\r\n\r\n"; char szCommand[_MAX_PATH * 3]; char szSDBPath[_MAX_PATH]; char szXMLPath[_MAX_PATH]; char szLOGPath[_MAX_PATH]; DWORD dwBytesWritten = 0; BOOL bRet; PROCESS_INFORMATION ProcInfo; STARTUPINFO si; GetDlgItemText(g_hMainDlg, IDC_EDIT1, g_szEditText, MAX_TEXT_BUF - 1); ExpandEnvironmentStrings("%windir%\\AppPatch\\systest.xml", szXMLPath, _MAX_PATH); ExpandEnvironmentStrings("%windir%\\AppPatch\\systest.sdb", szSDBPath, _MAX_PATH); ExpandEnvironmentStrings("%windir%\\AppPatch\\systest.log", szLOGPath, _MAX_PATH); HANDLE hFile = CreateFile( szXMLPath, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); if (hFile == INVALID_HANDLE_VALUE) { goto out; } if (!WriteFile(hFile, szHeader, sizeof(szHeader) - 1, &dwBytesWritten, NULL)) { goto out; } if (!WriteFile(hFile, g_szEditText, strlen(g_szEditText), &dwBytesWritten, NULL)) { goto out; } if (!WriteFile(hFile, szTrailer, sizeof(szTrailer) - 1, &dwBytesWritten, NULL)) { goto out; } CloseHandle(hFile); hFile = INVALID_HANDLE_VALUE; // Set up the start up info struct. ZeroMemory(&si,sizeof(STARTUPINFO)); si.cb = sizeof(STARTUPINFO); ZeroMemory(&ProcInfo, sizeof(PROCESS_INFORMATION)); sprintf(szCommand, "cmd /c shimdbc fix \"%s\" \"%s\" > \"%s\"", szXMLPath, szSDBPath, szLOGPath); bRet = CreateProcess(NULL, szCommand, NULL, NULL, FALSE, CREATE_NO_WINDOW, NULL, NULL, &si, &ProcInfo); if (!bRet) { MessageBox(g_hMainDlg, "Couldn't launch shimdbc to generate systest.sdb. Check systest.log for more.", "Error", MB_ICONEXCLAMATION); goto out; } if (WaitForSingleObject(ProcInfo.hProcess, 10000) == WAIT_OBJECT_0) { // wait a bit to ensure everything is all done, and the .SDB file is done closing. Sleep(100); // Set up the start up info struct. ZeroMemory(&si,sizeof(STARTUPINFO)); si.cb = sizeof(STARTUPINFO); ZeroMemory(&ProcInfo, sizeof(PROCESS_INFORMATION)); // pop open notepad to see the log sprintf(szCommand, "notepad \"%s\"", szLOGPath); bRet = CreateProcess(NULL, szCommand, NULL, NULL, FALSE, 0, NULL, NULL, &si, &ProcInfo); } out: if (hFile != INVALID_HANDLE_VALUE) { CloseHandle(hFile); } } void vEnumerateSystemDlls(HWND hDlg) { PDB pdb = NULL; WCHAR wszPath[_MAX_PATH]; HWND hList; TAGID tiDatabase; TAGID tiLibrary; TAGID tiDll; hList = GetDlgItem(hDlg, IDC_DLL_LIST); if (!hList) { goto out; } g_dwSystemDlls = 0; ExpandEnvironmentStringsW(L"%windir%\\AppPatch\\sysmain.sdb", wszPath, _MAX_PATH); pdb = SdbOpenDatabase(wszPath, DOS_PATH); if (!pdb) { goto out; } tiDatabase = SdbFindFirstTag(pdb, TAGID_ROOT, TAG_DATABASE); if (!tiDatabase) { goto out; } tiLibrary = SdbFindFirstTag(pdb, tiDatabase, TAG_LIBRARY); if (!tiLibrary) { goto out; } tiDll = SdbFindFirstTag(pdb, tiLibrary, TAG_SHIM); while (tiDll) { TAGID tiName; WCHAR wszName[_MAX_PATH]; wszName[0] = 0; tiName = SdbFindFirstTag(pdb, tiDll, TAG_NAME); if (tiName) { SdbReadStringTag(pdb, tiName, wszName, _MAX_PATH * sizeof(WCHAR)); } if (wszName[0]) { char szName[_MAX_PATH]; sprintf(szName, "%S", wszName); SendMessage(hList, LB_ADDSTRING, 0, (LPARAM)szName); g_dwSystemDlls++; } tiDll = SdbFindNextTag(pdb, tiLibrary, tiDll); } out: if (pdb) { SdbCloseDatabase(pdb); } } void vAddSelectedDlls(HWND hDlg) { HWND hList; DWORD *pdwItems = new DWORD[g_dwSystemDlls]; DWORD dwItems = 0; DWORD i; UINT unLine; char szTemp[MAX_LINE_LEN]; if (!pdwItems) { goto out; } hList = GetDlgItem(hDlg, IDC_DLL_LIST); if (!hList) { goto out; } UnpackEditLines(g_hMainDlg); // find the line and insert if necessary if (!bFindLine("", &unLine)) { if (!bFindLine("", &unLine)) { unLine = g_unEditLines + 1; } sprintf(szTemp, "%s", g_szExeIndent); InsertLine(unLine, szTemp); } dwItems = SendMessage(hList, LB_GETSELITEMS, g_dwSystemDlls, (LPARAM)pdwItems); for (i = 0; i < dwItems; ++i) { char szName[_MAX_PATH]; szName[0] = 0; SendMessage(hList, LB_GETTEXT, pdwItems[i], (LPARAM)szName); if (szName[0]) { sprintf(szTemp, "%s", g_szMatchIndent, szName); InsertLine(unLine, szTemp); } } PackEditLines(g_hMainDlg); out: return; } /* Does an in-place expansion of special characters for XML into the equivalents. Specifically, converts '&' to '&'. */ char *szConvertSpecialChars(char *szString) { char *szPtr; char *szEnd; assert(szString); szPtr = szString; szEnd = szString; while (*szEnd) { szEnd++; } szEnd++; // now points one past end // // now go looking for ampersands // while (*szPtr) { if (*szPtr == '&') { memmove(szPtr + 3, szPtr, szEnd-szPtr); memcpy(szPtr, "&", 4); szPtr += 3; szEnd += 3; } szPtr++; } return szString; }