home *** CD-ROM | disk | FTP | other *** search
/ Computer Shopper 275 / DPCS0111DVD.ISO / Toolkit / Audio-Visual / VirtualDub / Source / VirtualDub-1.9.10-src.7z / src / vdsvrlnk / main.cpp next >
Encoding:
C/C++ Source or Header  |  2009-09-14  |  11.9 KB  |  499 lines

  1. #include <crtdbg.h>
  2.  
  3. #include <windows.h>
  4.  
  5.  
  6. namespace Windows95 {
  7.  
  8. #include <svrapi.h>
  9.  
  10. };
  11.  
  12.  
  13. #include <lmcons.h>
  14. #include <lmserver.h>
  15. #include <lmapibuf.h>
  16. #include <vfw.h>
  17.  
  18. #define BUILDING_VDSVRLNK_DLL
  19. #include "vdserver.h"
  20.  
  21. typedef struct VDubPostedFrameserver {
  22.     LONG hwndServer;
  23.     int active_connects;
  24.     char name[56];
  25. } VDubPostedFrameserver;
  26.  
  27. #define MAXIMUM_FRAMESERVERS (256)
  28.  
  29. typedef struct VDubSharedHeap {
  30.     char    comp_name[16];
  31.     int        total_frameservers;
  32.     int        last_alloc;
  33.     DWORD    next_mmapID;
  34.     VDubPostedFrameserver fs_table[MAXIMUM_FRAMESERVERS];
  35. } VDubSharedHeap;
  36.  
  37. ////////////////////////////////////////////
  38.  
  39. VDubSharedHeap *heap;
  40. HANDLE            hHeap;
  41. HANDLE            hMutex;
  42.  
  43. ////////////////////////////////////////////
  44.  
  45. typedef    int (APIENTRY *LPNETSERVERGETINFO95)(
  46.                 const char FAR *     pszServer,
  47.                 short                sLevel,
  48.                 char FAR *           pbBuffer,
  49.                 unsigned short       cbBuffer,
  50.                 unsigned short FAR * pcbTotalAvail);
  51.  
  52. typedef    NET_API_STATUS (APIENTRY *LPNETSERVERGETINFONT)(
  53.                 LPWSTR                servername,
  54.                 DWORD                level,
  55.                 LPBYTE                *bufptr);
  56.  
  57. static void InitComputerAlias() {
  58.     union {
  59.         struct Windows95::server_info_50 si_95;
  60.         char buf[2048];
  61.     } si;
  62.     unsigned short needed_size;
  63.     HMODULE hDll = NULL;
  64.     FARPROC fpNetServerGetInfo = NULL;
  65.  
  66.     // For Windows 95, NetServerGetInfo() is in SVRAPI.DLL
  67.     // For Windows NT, NetServerGetInfo() is in NETAPI32.DLL
  68.     //
  69.     // Rather than test for the OS as Microsoft suggests, we simply
  70.     // try SVRAPI.DLL first, and then NETAPI32.  If both fail, then
  71.     // fake a computer name with 'ANON' and then 8 hex digits of the
  72.     // current tick value.
  73.  
  74.     if (hDll = LoadLibrary("svrapi.dll")) {
  75.         fpNetServerGetInfo = GetProcAddress(hDll, "NetServerGetInfo");
  76.  
  77.         if (fpNetServerGetInfo && !((LPNETSERVERGETINFO95)fpNetServerGetInfo)(NULL, 50, (char *)&si, sizeof si, &needed_size)) {
  78.             strncpy(heap->comp_name, si.si_95.sv50_name, sizeof heap->comp_name);
  79.             heap->comp_name[sizeof heap->comp_name-1] = 0;
  80.  
  81.             FreeLibrary(hDll);
  82.             return;
  83.         }
  84.  
  85.         FreeLibrary(hDll);
  86.     }
  87.  
  88.     // Okay, that didn't work -- try Windows NT/2000.
  89.  
  90.     if (!fpNetServerGetInfo && (hDll = LoadLibrary("netapi32.dll"))) {
  91.         SERVER_INFO_100 *psi100;
  92.  
  93.         fpNetServerGetInfo = GetProcAddress(hDll, "NetServerGetInfo");
  94.         if (fpNetServerGetInfo && !((LPNETSERVERGETINFONT)fpNetServerGetInfo)(NULL, 100, (LPBYTE *)&psi100)) {
  95.  
  96.             WideCharToMultiByte(CP_ACP, 0,  (LPWSTR)psi100->sv100_name, -1, heap->comp_name, sizeof heap->comp_name, NULL, NULL);
  97. //            strncpy(heap->comp_name, psi100->sv100_name, sizeof heap->comp_name);
  98. //            heap->comp_name[sizeof heap->comp_name-1] = 0;
  99.  
  100.             void *lpNetApiBufferFree;
  101.  
  102.             if (lpNetApiBufferFree = GetProcAddress(hDll, "NetApiBufferFree"))
  103.                 ((NET_API_STATUS (APIENTRY *)(LPVOID ))lpNetApiBufferFree)(psi100);
  104.  
  105.             FreeLibrary(hDll);
  106.             return;
  107.         }
  108.  
  109.         FreeLibrary(hDll);
  110.     }
  111.  
  112.     // Ugh.
  113.  
  114.     wsprintf(heap->comp_name, "Anon%08lx", GetTickCount());
  115. }
  116.  
  117. static BOOL InitSharedSpace() {
  118.     BOOL fInit;
  119.  
  120.     //////////
  121.  
  122.     hHeap = CreateFileMapping(    INVALID_HANDLE_VALUE,
  123.                                 NULL,
  124.                                 PAGE_READWRITE,
  125.                                 0,
  126.                                 sizeof(VDubSharedHeap),
  127.                                 "VirtualDub Server System Window");
  128.  
  129.     if (hHeap == NULL) return FALSE;
  130.  
  131.     fInit = (GetLastError() != ERROR_ALREADY_EXISTS);
  132.  
  133.     _RPT0(0,"shared heap created\n");
  134.  
  135.     heap = (VDubSharedHeap *)MapViewOfFile(
  136.                                 hHeap,
  137.                                 FILE_MAP_WRITE,
  138.                                 0,
  139.                                 0,
  140.                                 0);
  141.  
  142.     if (!heap) {
  143.         CloseHandle(hHeap);
  144.         return FALSE;
  145.     }
  146.  
  147.     _RPT0(0,"heap mapped into subspace... preparing to go to warp.\n");
  148.  
  149.     if (!(hMutex = CreateMutex(NULL, FALSE, "VirtualDub Server System Mutex")))
  150.         return FALSE;
  151.  
  152.     _RPT0(0,"mutex obtained\n");
  153.  
  154.     if (!fInit) return TRUE;
  155.  
  156.     memset(heap, 0, sizeof VDubSharedHeap);
  157.  
  158.     InitComputerAlias();
  159.  
  160.     return TRUE;
  161. }
  162.  
  163. // Are you a Ranma 1/2 fan?
  164.  
  165. static void ranko() {
  166.     _RPT1(0,"server: lock mutex %p\n", hMutex);
  167.     WaitForSingleObject(hMutex, INFINITE);
  168. }
  169.  
  170. static void ranma() {
  171.     _RPT1(0,"server: unlock mutex %p\n", hMutex);
  172.     if (!ReleaseMutex(hMutex)) {
  173.         _RPT0(0,"Hey!  I didn't own the mutex!\n");
  174.     }
  175. }
  176.  
  177. ////////////////////////////////////////////
  178.  
  179. //extern "C" __declspec(dllexport) BOOL WINAPI DllMain(HANDLE hModule, ULONG ulReason, LPVOID lpReserved);
  180.  
  181. HMODULE ghModule;
  182.  
  183. BOOL APIENTRY DllMain(HANDLE hModule, ULONG ulReason, LPVOID lpReserved) {
  184.  
  185.     switch(ulReason) {
  186.     case DLL_PROCESS_ATTACH:
  187.         ghModule = (HMODULE)hModule;
  188.  
  189.         _RPT0(0,"Process attach\n");
  190.  
  191.         return InitSharedSpace();
  192.  
  193.     case DLL_PROCESS_DETACH:
  194.         UnmapViewOfFile(heap);
  195.         CloseHandle(hHeap);
  196.         break;
  197.     }
  198.  
  199.     return TRUE;
  200. }
  201.  
  202. /////////////////////////////////////////////
  203.  
  204. class CVDubAnimConnection : public IVDubAnimConnection {
  205. private:
  206.     VDubPostedFrameserver *frameserver;
  207.     HANDLE hArena;
  208.     char *arena;
  209.     long lArenaSize;
  210.     DWORD dwSessionID;
  211.     long lFrameSize;
  212.  
  213. public:
  214.     CVDubAnimConnection(VDubPostedFrameserver *);
  215.     ~CVDubAnimConnection();
  216.  
  217.     BOOL init();
  218.  
  219.     BOOL hasAudio();
  220.     BOOL readStreamInfo(AVISTREAMINFO *lpsi, BOOL fAudio, long *lpFirst, long *lpLast);
  221.     int readFormat(void *ptr, BOOL fAudio);
  222.     int readVideo(long lSample, void *lpBuffer);
  223.     int readAudio(long lSample, long lCount, void *lpBuffer, long cbBuffer, long *lplBytes, long *lplSamples);
  224. };
  225.  
  226.  
  227. ///////////////////////////////////////////
  228.  
  229. CVDubAnimConnection::CVDubAnimConnection(VDubPostedFrameserver *vdpf) {
  230.     frameserver = vdpf;
  231.     dwSessionID = 0;
  232.     hArena = INVALID_HANDLE_VALUE;
  233.     arena = NULL;
  234. }
  235.  
  236. CVDubAnimConnection::~CVDubAnimConnection() {
  237.     if (dwSessionID) SendMessage((HWND)LongToHandle(frameserver->hwndServer), VDSRVM_CLOSE, 0, dwSessionID);
  238.  
  239.     if (arena) UnmapViewOfFile(arena);
  240.     if (hArena) CloseHandle(hArena);
  241.  
  242.     --frameserver->active_connects;
  243. }
  244.  
  245. BOOL CVDubAnimConnection::init() {
  246.     LONG lArenaSize;
  247.     char buf[16];
  248.     DWORD mmapID;
  249.  
  250.     // find out how big of an arena we need
  251.  
  252.     lArenaSize = SendMessage((HWND)LongToHandle(frameserver->hwndServer), VDSRVM_BIGGEST, 0, 0);
  253.  
  254.     if (!lArenaSize) return FALSE;
  255.  
  256.     // create a name for us
  257.  
  258.     ranko();
  259.     wsprintf(buf, "VDUBF%08lx", mmapID = heap->next_mmapID++);
  260.     ranma();
  261.  
  262.     // create a shared arena and map a window for us
  263.  
  264.     hArena = CreateFileMapping(
  265.             INVALID_HANDLE_VALUE,
  266.             NULL,
  267.             PAGE_READWRITE,
  268.             0,
  269.             lArenaSize,
  270.             buf);
  271.  
  272.     if (!hArena) return FALSE;
  273.  
  274.     _RPT0(0,"Have arena.\n");
  275.  
  276.     arena = (char *)MapViewOfFile(hArena, FILE_MAP_WRITE, 0, 0, lArenaSize);
  277.  
  278.     if (!arena) return FALSE;
  279.  
  280.     _RPT0(0,"Arena mapped.\n");
  281.  
  282.     // hail the server
  283.  
  284.     dwSessionID = SendMessage((HWND)LongToHandle(frameserver->hwndServer), VDSRVM_OPEN, lArenaSize, mmapID);
  285.  
  286.     if (!dwSessionID) return FALSE;        // no response, Captain
  287.  
  288.     _RPT0(0,"Server responded.\n");
  289.  
  290.     // on screen!  get me the video format!
  291.  
  292.     if (SendMessage((HWND)LongToHandle(frameserver->hwndServer), VDSRVM_REQ_FORMAT, 0, dwSessionID) <= 0)
  293.         return FALSE;
  294.  
  295.     {
  296.         BITMAPINFOHEADER *bmih = (BITMAPINFOHEADER *)arena;
  297.  
  298.         lFrameSize = bmih->biSizeImage;
  299.     }
  300.  
  301.     _RPT0(0,"Connect!\n");
  302.  
  303.     return TRUE;
  304. }
  305.  
  306. BOOL CVDubAnimConnection::hasAudio() {
  307.     return VDSRVERR_OK == SendMessage((HWND)LongToHandle(frameserver->hwndServer), VDSRVM_REQ_STREAMINFO, 1, dwSessionID);
  308. }
  309.  
  310. BOOL CVDubAnimConnection::readStreamInfo(AVISTREAMINFO *lpsi, BOOL fAudio, long *lpFirst, long *lpLast) {
  311.     if (VDSRVERR_OK == SendMessage((HWND)LongToHandle(frameserver->hwndServer), VDSRVM_REQ_STREAMINFO, !!fAudio, dwSessionID)) {
  312.         if (lpsi) memcpy(lpsi, arena+8, sizeof(AVISTREAMINFO));
  313.         if (lpFirst) *lpFirst = *(long *)(arena+0);
  314.         if (lpLast) *lpLast = *(long *)(arena+4);
  315.         return TRUE;
  316.     }
  317.     return FALSE;
  318. }
  319.  
  320. int CVDubAnimConnection::readFormat(void *ptr, BOOL fAudio) {
  321.     int err;
  322.  
  323.     err = SendMessage((HWND)LongToHandle(frameserver->hwndServer), VDSRVM_REQ_FORMAT, !!fAudio, dwSessionID);
  324.  
  325.     if (err<0) return err;
  326.  
  327.     if (ptr) memcpy(ptr, arena, err);
  328.  
  329.     return err;
  330. }
  331.  
  332. int CVDubAnimConnection::readVideo(long lSample, void *lpBuffer) {
  333.     int err;
  334.  
  335.     _RPT0(0,"Sending message...\n");
  336.     if (VDSRVERR_OK != (err = SendMessage((HWND)LongToHandle(frameserver->hwndServer), VDSRVM_REQ_FRAME, lSample, dwSessionID)))
  337.         return err;
  338.  
  339.     _RPT2(0,"Copying %ld bytes to user buffer from arena %p\n", lFrameSize, arena);
  340.     memcpy(lpBuffer, arena, lFrameSize);
  341.     _RPT0(0,"Copy completed.\n");
  342.  
  343.     return VDSRVERR_OK;
  344. }
  345.  
  346. int CVDubAnimConnection::readAudio(long lSample, long lCount, void *lpBuffer, long cbBuffer, long *lplBytes, long *lplSamples) {
  347.     int err;
  348.  
  349.     *(long *)(arena+0) = lCount;
  350.     *(long *)(arena+4) = cbBuffer;
  351.  
  352.     if (VDSRVERR_OK != (err = SendMessage((HWND)LongToHandle(frameserver->hwndServer), lpBuffer?VDSRVM_REQ_AUDIO:VDSRVM_REQ_AUDIOINFO, lSample, dwSessionID)))
  353.         return err;
  354.  
  355.     if (lplSamples) *lplSamples = *(long *)(arena + 4);
  356.     if (lplBytes) *lplBytes = *(long *)(arena + 0);
  357.  
  358.     if (lpBuffer) memcpy(lpBuffer, arena+8, *lplBytes);
  359.  
  360.     return VDSRVERR_OK;
  361. }
  362.  
  363. /////////////////////////////////////////////////////////////////////////////
  364. //
  365. //        CVDubServerLink
  366. //
  367. /////////////////////////////////////////////////////////////////////////////
  368.  
  369. class CVDubServerLink : public IVDubServerLink {
  370. public:
  371.     void                    GetComputerName(char *buf);
  372.     IVDubAnimConnection    *    FrameServerConnect(char *fs_name);
  373.     void                    FrameServerDisconnect(IVDubAnimConnection *);
  374.     int                        CreateFrameServer(char *name, HWND hwndServer);
  375.     void                    DestroyFrameServer(int handle);
  376. };
  377.  
  378. static CVDubServerLink i_dubserver;
  379.  
  380. void CVDubServerLink::GetComputerName(char *buf) {
  381.     lstrcpy(buf, heap->comp_name);
  382. }
  383.  
  384. IVDubAnimConnection *CVDubServerLink::FrameServerConnect(char *fs_name) {
  385.     int i;
  386.     char c,*s;
  387.     CVDubAnimConnection *cvdac;
  388.  
  389.     // look for a slash (/) that delimits the computer name
  390.  
  391.     _RPT1(0,"Looking for server [%s]\n",fs_name);
  392.  
  393.     s = fs_name;
  394.     while(c=*s++) if (c=='/') {
  395.         char *s1, *s2, d;
  396.  
  397.         // we found the slash... now compare that to our computer name
  398.  
  399.         s1 = fs_name;
  400.         s2 = heap->comp_name;
  401.  
  402.         do {
  403.             c = *s1++;
  404.             d = *s2++;
  405.         } while(c==d && c!='/' && d);
  406.  
  407.         if (c!='/' || d)
  408.             return NULL;    // not our computer, and we don't do remote yet
  409.  
  410.         // yay!  it's us!
  411.  
  412.         break;
  413.     }
  414.  
  415.     if (!c) s=fs_name;
  416.  
  417.     // look through the list and see if we can spot the server
  418.  
  419.     _RPT1(0,"Computer name ok, looking for server [%s]\n", s);
  420.  
  421.     ranko();
  422.  
  423.     for(i=0; i<MAXIMUM_FRAMESERVERS; i++) {
  424.         if (heap->fs_table[i].hwndServer && !_strnicmp(heap->fs_table[i].name, s, sizeof heap->fs_table[i].name - 1))
  425.             break;
  426.     }
  427.  
  428.     if (i >= MAXIMUM_FRAMESERVERS) {
  429.         _RPT0(0,"Computer not found\n");
  430.         ranma();
  431.         return NULL;
  432.     }
  433.  
  434.     // hey!  we spotted the server!  now lock it before it goes
  435.     // away!
  436.  
  437.     _RPT0(0,"Server found\n");
  438.  
  439.     ++heap->fs_table[i].active_connects;
  440.  
  441.     // allocate a CVDubAnimConnection
  442.  
  443.     if (cvdac = new CVDubAnimConnection(&heap->fs_table[i])) {
  444.         // try to initialize it
  445.  
  446.         if (!cvdac->init()) {
  447.             delete cvdac;
  448.             cvdac = NULL;
  449.         }
  450.     } else --heap->fs_table[i].active_connects;
  451.  
  452.     ranma();
  453.  
  454.     return cvdac;
  455. }
  456.  
  457. void CVDubServerLink::FrameServerDisconnect(IVDubAnimConnection *idac) {
  458.     delete (CVDubAnimConnection *)idac;
  459. }
  460.  
  461. int CVDubServerLink::CreateFrameServer(char *name, HWND hwndServer) {
  462.     int i;
  463.  
  464.     if (heap->total_frameservers >= MAXIMUM_FRAMESERVERS)
  465.         return -1;
  466.  
  467.     ranko();
  468.  
  469.     i = heap->last_alloc;
  470.     while(heap->fs_table[i].active_connects || heap->fs_table[i].hwndServer)
  471.         i = (i+1) % MAXIMUM_FRAMESERVERS;
  472.  
  473.     heap->fs_table[i].hwndServer = HandleToLong(hwndServer);
  474.     strncpy(heap->fs_table[i].name, name, sizeof heap->fs_table[i].name);
  475.  
  476.     heap->fs_table[i].name[(sizeof heap->fs_table[i].name)-1] = 0;
  477.  
  478.     heap->last_alloc = i;
  479.  
  480.     ranma();
  481.  
  482.     return i;
  483. }
  484.  
  485. void CVDubServerLink::DestroyFrameServer(int handle) {
  486.     if (handle<0 || handle>=MAXIMUM_FRAMESERVERS)
  487.         return;
  488.  
  489.     ranko();
  490.  
  491.     heap->fs_table[handle].hwndServer = NULL;
  492.  
  493.     ranma();
  494. }
  495.  
  496. extern "C" __declspec(dllexport) IVDubServerLink *__cdecl GetDubServerInterface() {
  497.     return &i_dubserver;
  498. }
  499.